// PhotoObject a.k.a. phob
var PhotoObject = function(fullUrl, thumbUrl, profileUrl, displayName) {
    this.fullUrl = fullUrl;
    this.thumbUrl = thumbUrl;
    this.profileUrl = profileUrl;
    this.displayName = displayName;
};

var global = {
    perpage : 9,
    errorMsg: "An unknown error has occurred with MySpace.",
    noimages: "No images to display.", 
    profileSurface: opensocial.getEnvironment().getSupportedSurfaces()[MyOpenSpace.Surface.Field.PROFILE_RIGHT],
    browser: {
        isIE : (navigator.userAgent.indexOf("MSIE") != -1),
        isIE6 : (navigator.userAgent.indexOf("MSIE 6") != -1),
        isIE7 : (navigator.userAgent.indexOf("MSIE 7") != -1),
        isSafari : (navigator.userAgent.indexOf("AppleWebKit") != -1),
        isFirefox : (navigator.userAgent.indexOf("Firefox") != -1),
        isOpera : (navigator.userAgent.indexOf("Opera") != -1)
    }
};

LeftNav = Class.create();
LeftNav.prototype = {

    navlinks : null,
    
    initialize: function() {
        this.navlinks = $$('#cellLeft A.navItem');
        for (var i=0; i < this.navlinks.length; i++) {
            Event.observe(this.navlinks[i], 'click', this.handleLeftNavClick.bindAsEventListener(this), false);
        }
    },

    handleLeftNavClick: function(evnt) {
        var elt = Event.findElement(evnt, 'A');
        var targetId = elt.id.split("_")[1];

        var expandedlinks = $$('#cellLeft A.expanded');
        for (var i=0; i < expandedlinks.length; i++) {
            linkId = expandedlinks[i].id;
            divId = linkId.split("_")[1];
            if(linkId != elt.id) {
                Element.removeClassName(linkId, 'expanded');
                new Effect.SlideUp(divId, {duration:0.25,
                                            afterFinish: function() {
                                                var elt = $(divId);
                                                elt.style.bottom = '';
                                                elt.style.height = '';
                                            }
                                          });
            }
        }

        if (Element.hasClassName(elt, 'expanded')) {
            Element.removeClassName(elt, 'expanded');
            new Effect.SlideUp(targetId, {duration:0.25,
                                            afterFinish: function() {
                                                var elt = $(targetId);
                                                elt.style.bottom = '';
                                                elt.style.height = '';
                                            }
                                         });
        } else {
            Element.addClassName(elt, 'expanded');
            new Effect.SlideDown(targetId, {
                    duration:0.25,
                    afterFinish: function() {
                        var elt = $(targetId);
                        elt.style.bottom = '';
                        elt.style.height = '';
                        // hardcoding focus calls to search fields
                        // because of scriptaculous handling
                        if (targetId == "recentuser")
                            $("username").activate();
                        if (targetId == "search")
                            $("query").activate();
                    }
                });
        }
    }
};

PhotosControl = Class.create();
PhotosControl.prototype = {
    idPrefix: "",
    inputFieldId: "",
    pagination: true,
    searchField: true,
    
    initialize: function() {
        this.fetcher = null;
        this.currentPage = 1;
        this.totalpages = null;

        // dont run pageInt when just extending class
        // only init when valid instance
        // (e.g. PhotosControl must have photoRequest)
        if (this.photoRequest) {
            this.pageInit();
        }

    },
    
    pageInit: function(){
        // handle events
        this.photoRequestListener = this.photoRequest.bindAsEventListener(this);
        if (this.searchField) 
            Event.observe(this.idPrefix + "Form", "submit", this.photoRequestListener, false);
        else 
            Event.observe("link_" + this.idPrefix, "click", this.photoRequestListener, false);
        if (this.pagination) {
            this.firstPageListener = this.firstPage.bindAsEventListener(this);
            this.prevPageListener = this.prevPage.bindAsEventListener(this);
            this.nextPageListener = this.nextPage.bindAsEventListener(this);
            this.lastPageListener = this.lastPage.bindAsEventListener(this);
            // dont display pagination buttons until after a search
            if (this.searchField) {
                PaginationUtil.setDisabled($(this.idPrefix + "NextPage"), this.nextPageListener);
                PaginationUtil.setDisabled($(this.idPrefix + "LastPage"), this.lastPageListener);
                PaginationUtil.setDisabled($(this.idPrefix + "PrevPage"), this.prevPageListener);
                PaginationUtil.setDisabled($(this.idPrefix + "FirstPage"), this.firstPageListener);
            }
        }
    },

    handleSuccess: function(data) {
        if (data) {
            // set totalpages if not already set
            if (this.totalpages == null) {
                this.totalpages = data.totalpages;
            }
            var container = $(this.idPrefix + "Results");
            this.clearPhotos(container);
            if (this.totalpages > 0) {
                // insert response photos
                var li = null;
                for (j = 0; j < PhotoFetcher.prototype.perpage; j++) {
                    if (data[j]) {
                        var phob = new PhotoObject(data[j].photo.url, data[j].photo.thumb, data[j].photo.browseurl);
                        li = pageControl.getAddableThumbnailListItem(phob.thumbUrl, Object.toJSON(phob));
                        container.appendChild(li);
                    }
                }
            } else {
                var div = Builder.node('div',
                            {className: "messageText"},
                            global.noimages);
                container.appendChild(div);
            }
        }
        this.stopProgress();
    },
    
    handleFailure: function(error) {
        var errorTitle, errorMsg;
        if (error.msg) { // PB API error
            if (error.code == "108") {
                errorTitle = "Only public Photobucket albums are searchable.";
                errorMsg = "Albums can be set to public in Photobucket account options.";
            }
            else {
                errorTitle = "An error has occurred with Photobucket."
                errorMsg = error.msg;
            } 
        } else if (error.errorMessage) { // Myspace proxy error
            errorTitle = "An error has occurred with MySpace."
            errorMsg = error.errorMessage;
        } else if (error.errors && error.errors.length > 0) {
            errorTitle = "An error has occurred with MySpace."
            errorMsg = error.errors[0];
        } else {
            errorTitle = global.errorMsg
        }
        this.clearPhotos($(this.idPrefix + "Results"));
        this.stopProgress();
        Event.stopObserving(this.idPrefix + "Form", "submit", this.photoRequestListener, false);
        new AlertBox({
                style: "error",
                title: errorTitle,
                message: errorMsg
            },
            function() {
                Event.observe(this.idPrefix + "Form", "submit", this.photoRequestListener, false);
            }.bind(this)
        );
    },
    
    startProgress: function() {
        Element.show(this.idPrefix + "Shroud");
        Element.show(this.idPrefix + "Indicator");
    },
    
    stopProgress: function() {
        Element.hide(this.idPrefix + "Shroud");
        Element.hide(this.idPrefix + "Indicator");
        // fix pagination buttons
        if (this.pagination) {
            if (this.currentPage < this.totalpages) {
                PaginationUtil.setEnabled($(this.idPrefix + "NextPage"), this.nextPageListener);
                PaginationUtil.setEnabled($(this.idPrefix + "LastPage"), this.lastPageListener);
            } else {
                PaginationUtil.setDisabled($(this.idPrefix + "NextPage"), this.nextPageListener);
                PaginationUtil.setDisabled($(this.idPrefix + "LastPage"), this.lastPageListener);
            }
            if (this.currentPage > 1) {
                PaginationUtil.setEnabled($(this.idPrefix + "PrevPage"), this.prevPageListener);
                PaginationUtil.setEnabled($(this.idPrefix + "FirstPage"), this.firstPageListener);
            } else {
                PaginationUtil.setDisabled($(this.idPrefix + "PrevPage"), this.prevPageListener);
                PaginationUtil.setDisabled($(this.idPrefix + "FirstPage"), this.firstPageListener);
            }
        }
        // activate search input field
        if (this.inputFieldId != "")
            $(this.inputFieldId).activate();
    },
    
    clearPhotos: function(container) {
        // clear out old images
        if (container) {
            des = Element.immediateDescendants(container);
            for(i = 0 ; i < des.length; i++) {
                des[i].remove();
            }
        }
    },
    
    firstPage: function() {
        if (this.currentPage != 1) {
            this.startProgress();
            this.currentPage = 1;
            this.fetcher.getPage(this.currentPage);
        }
    },
    
    lastPage: function() {
        if (this.fetcher && (this.currentPage != this.fetcher.data.totalpages)) {
            this.startProgress();
            this.currentPage = this.totalpages;
            this.fetcher.getPage(this.currentPage);
        }
    },
    
    prevPage: function() {
        if (this.currentPage > 1) {
            this.startProgress();
            this.currentPage -= 1;
            this.fetcher.getPage(this.currentPage);
        }
    },

    nextPage: function() {
        if (this.fetcher && (this.currentPage < this.totalpages)) {
            this.startProgress();
            this.currentPage += 1;
            this.fetcher.getPage(this.currentPage);
        }
    }
    
};

var SearchPhotosControl = Class.create();
SearchPhotosControl.prototype = Object.extend(new PhotosControl(), {
    idPrefix: "search",
    inputFieldId: "query",
    photoRequest: function(evnt) {
        $('searchcategoryResults').style.display = 'none';
        this.startProgress();
        this.fetcher = new SearchPhotoFetcher($(this.inputFieldId).value, this.handleSuccess.bind(this), this.handleFailure.bind(this));
            this.currentPage = 1;
        this.totalpages = null;
        this.fetcher.getPage(this.currentPage);
    }
});

var RecentUserPhotosControl = Class.create();
RecentUserPhotosControl.prototype = Object.extend(new PhotosControl(), {
    idPrefix: "recentuser",
    inputFieldId: "username",
    photoRequest: function(evnt) {
        this.startProgress();
        this.fetcher = new RecentUserPhotoFetcher($(this.inputFieldId).value, this.handleSuccess.bind(this), this.handleFailure.bind(this));
        this.currentPage = 1;
        this.totalpages = null;
        this.fetcher.getPage(this.currentPage);
    }
});

var BackgroundPhotosControl = Class.create();
BackgroundPhotosControl.prototype = Object.extend(new PhotosControl(), {
    idPrefix: "background",
    searchField: false,

    initialize: function() {
        this.fetcher = null;
        this.currentPage = 1;
        this.totalpages = null;

        if (this.photoRequest) {
            this.pageInit();
        }

        if ($("clear_background")) {
            Event.observe("clear_background", "click", this.clearBackgroundClick.bindAsEventListener(this), false);
        }
    },
    clearBackgroundClick: function(evnt) {
        pageControl.swfGridControl.setBackground('');
    },
    photoRequest: function(evnt) {
        var children = $('backgroundResults').childElements();
        if(children.length > 0)
            return;
        this.startProgress();
        this.fetcher = new BackgroundPhotoFetcher(null, this.handleSuccess.bind(this), this.handleFailure.bind(this));
        this.fetcher.getPage(this.currentPage);
    } ,
    
    handleSuccess: function(data) {
        if (data) {
            this.totalpages = data.totalpages;
//            this.currentPage = data.page;
            var container = $(this.idPrefix + "Results");
            this.clearPhotos(container);
            data = data['backgroundresults'];
            var li = null;
            for(key in data) {
                li = pageControl.getAddableBackgroundListItem(data[key]);
                container.appendChild(li);
            }
            // Event.stopObserving("link_background", "click", this.PhotoRequest(), false);
        }
        this.stopProgress();
    }
});

var SearchCategoryPhotosControl = Class.create();
SearchCategoryPhotosControl.prototype = Object.extend(new PhotosControl(), {
    idPrefix: "search",
    searchField: false,
    pagination: false,
    photoRequest: function(evnt) {
        var children = $('searchcategoryResults').childElements();
        if(children.length > 0)
            return;
        this.fetcher = new SearchCategoryPhotoFetcher(null, this.handleSuccess.bind(this), this.handleFailure.bind(this));
        this.currentPage = 1;
        this.totalpages = null;
        this.fetcher.getPage(this.currentPage);
    }
});


var PhotoFetcher = Class.create();
PhotoFetcher.prototype = {
    method: null,
    key: null,
    collectionRoot: null,
    perpage: global.perpage,
    
    initialize : function(value, doSuccess, doFailure) {
        this.data = null;
        this.params = {"perpage": this.perpage};
        if(this.key != null)
            this.params[this.key] = value;
        this.doSuccess = doSuccess;
        this.doFailure = doFailure;
    },

    getPage : function(page) {
        this.params["page"] = page;
        var req = new APIRequest(this.method, true, this.params, this.handleSuccess.bind(this), this.handleFailure.bind(this), false, "POST");
        
    },
    
    handleSuccess : function(data) {
        this.data = data[this.collectionRoot];
        if (this.doSuccess) this.doSuccess(this.data);
    },
    
    handleFailure: function(data){
        // MySpace error
        if (data.errorCode || (data.errors && data.errors.length > 0)) {
            if (this.doFailure) this.doFailure(data);
        }
        // PB error
        else if (data.error) {
            if (this.doFailure) this.doFailure(data.error);
        } else {
            if (this.doFailure) this.doFailure(data);
        }
    }
};

var RecentUserPhotoFetcher = Class.create();
RecentUserPhotoFetcher.prototype = Object.extend(new PhotoFetcher(), {
    method: "getrecentuserphotos",
    key: "username",
    collectionRoot: "userphotos"
});

var SearchPhotoFetcher = Class.create();
SearchPhotoFetcher.prototype = Object.extend(new PhotoFetcher(), {
    method: "search",
    key: "query",
    collectionRoot: "searchresults"
});

var BackgroundPhotoFetcher = Class.create();
BackgroundPhotoFetcher.prototype = Object.extend(new PhotoFetcher(), {
    method: "getbackgroundphotos",
    key: null,
    collectionRoot: "backgroundresults",
    handleSuccess : function(data) {
        this.data = data;
        if (this.doSuccess) this.doSuccess(data);
    }
});

var SearchCategoryPhotoFetcher = Class.create();
SearchCategoryPhotoFetcher.prototype = Object.extend(new PhotoFetcher(), {
    method: "getsearchcategoryphotos",
    key: null,
    collectionRoot: "searchcategoryResults",
    handleSuccess: function(data) {
        data = data[this.collectionRoot];
        if (data) {
            var container = $(this.collectionRoot);
            // insert response photos
            var li = null;
            for(key in data) {
                li = pageControl.getAddableSearchCategoryListItem(key, data[key]);
                container.appendChild(li);
            }
        }
    }
});

ProfileGridControl = Class.create();
ProfileGridControl.prototype = {
    gridId: 'containerProfileGrid',
    maxItems: null,
    defaultMaxItems: 9,
    cookieName: "Photobucket-opensocial",
    
    initialize: function(maxItems) {
        this.eltGrid = null;
        this.eltGridItems = null;
        this.selected = new Hash();
        
        if (!maxItems) this.maxItems = this.defaultMaxItems;
        else this.maxItems = maxItems;
        
        this.eltGrid = $(this.gridId);

        // read domain cookie if available
        var cookie = CookiesUtil.readCookie(this.cookieName);
        if (cookie && cookie !== "undefined") {
            var a = cookie.split(",");
            var count = 0;
            for (i = 0; i < a.length; i++) {
                if (a[i]) {
                    var item = {};
                    item[count] = a[i];
                    this.selected.merge(item);
    
                    // pre-load photos from cookie
                    var li = pageControl.getStaticThumbnailListItem(a[i]);
                    li.id = "image_" + count;
                    count += 1;
                    this.eltGrid.appendChild(li);
                }
            }
        }
    }
    
};

CookiesUtil = {
    createCookie: function(name, value, days) {
        if (days) {
            var date = new Date();
            date.setTime(date.getTime()+(days*24*60*60*1000));
            var expires = "; expires="+date.toGMTString();
        }
        else var expires = "";
        document.cookie = name+"="+value+expires+"; path=/";
    },
    
    readCookie : function(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for(var i=0;i < ca.length;i++) {
            var c = ca[i];
            while (c.charAt(0)==' ') c = c.substring(1,c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
        }
        return null;
    }
};

PaginationUtil = {
    
    setDisabled: function(elt,listener) {
        var pageClasses = Element.classNames(elt).grep("^pagination_");
        if(elt && pageClasses.size() > 0){
            pageClasses.each(function(c) {
                Element.classNames(elt).add("disabled_" + c);
                Event.stopObserving(elt, "click", listener, false);
            });
        }
    },
    
    setEnabled: function(elt,listener) {
        var pageClasses = Element.classNames(elt).grep("^pagination_");
        if(elt && pageClasses.size() > 0){
            var disabledClasses = Element.classNames(elt).grep("^disabled_");
            if (disabledClasses.size() > 0) {
                disabledClasses.each(function(c) {
                    Element.classNames(elt).remove(c);
                });
            }
            Event.stopObserving(elt, "click", listener, false);
            Event.observe(elt, "click", listener, false);
        }
    }
};

FriendsFetcher = Class.create();
FriendsFetcher.prototype = {
    perpage: global.perpage,
    numPages: null,
    
    initialize: function() {
        this.currentPage = 1;
        this.container = $("containerMyspaceFriends");
        
        this.firstPageListener = this.firstPage.bindAsEventListener(this);
        this.prevPageListener = this.prevPage.bindAsEventListener(this);
        this.nextPageListener = this.nextPage.bindAsEventListener(this);
        this.lastPageListener = this.lastPage.bindAsEventListener(this);
        this.getFriendsListener = this.getFriends.bindAsEventListener(this);
        
        Event.observe("link_myspaceFriendsPics", "click", this.getFriendsListener, false);
        Event.observe("myspaceFriendsPicsHeader", "click", this.getFriendsListener, false);
        $("myspaceBack").hide();
    },
    
    getFriends: function() {
        this.startProgress();
            
        var req = opensocial.newDataRequest();
            
        // friends request
        var params = {};
        params[opensocial.DataRequest.PeopleRequestFields.FIRST] = ((this.currentPage - 1) * this.perpage) + 1;
        params[opensocial.DataRequest.PeopleRequestFields.MAX] = this.perpage;
        // Don't specify TOP_FRIENDS, all other params will be ignored
        // params[opensocial.DataRequest.PeopleRequestFields.SORT_ORDER] = opensocial.DataRequest.SortOrder.TOP_FRIENDS;
        var friendsReq = req.newFetchPeopleRequest(opensocial.DataRequest.Group.OWNER_FRIENDS, params);
        req.add(friendsReq, "ownerFriends");
        req.send(this.friendsResponse.bind(this));
    
    },
    
    friendsResponse: function(data){
        if (data.hadError()) {
            return false;
        }
        
        // clear out container, if necessary
        this.clearContainer(this.container);
        
        // get friends response
        var friends = data.get("ownerFriends").getData();
        
        // calculate number of pages based on total number of photos 
        if (this.numPages == null) {
            var totalSize = friends.getTotalSize();
            this.numPages = Math.ceil(totalSize / this.perpage);
        }
        
        friends.each(function(friendData){
            var friendId = friendData.getId();
            var friendName = friendData.getDisplayName();
            var friendThumbnailUrl = friendData.getField(opensocial.Person.Field.THUMBNAIL_URL);
            this.container.appendChild(pageControl.getFriendListItem({
                id: friendId,
                thumbUrl: friendThumbnailUrl,
                name: friendName
            }));
        }.bind(this));
        
        this.stopProgress();
    },

    startProgress: function() {
        if (!global.browser.isIE) {
            Element.show("myspaceFriendsShroud");
            Element.show("myspaceFriendsIndicator");
        }
    },
    
    stopProgress: function() {
        if (!global.browser.isIE) {
            Element.hide("myspaceFriendsShroud");
            Element.hide("myspaceFriendsIndicator");
        }
        // fix pagination buttons
        if (this.currentPage < this.numPages) {
            PaginationUtil.setEnabled($("myspaceFriendsNextPage"), this.nextPageListener);
            PaginationUtil.setEnabled($("myspaceFriendsLastPage"), this.lastPageListener);
        } else {
            PaginationUtil.setDisabled($("myspaceFriendsNextPage"), this.nextPageListener);
            PaginationUtil.setDisabled($("myspaceFriendsLastPage"), this.lastPageListener);
        }
        if (this.currentPage > 1) {
            PaginationUtil.setEnabled($("myspaceFriendsPrevPage"), this.prevPageListener);
            PaginationUtil.setEnabled($("myspaceFriendsFirstPage"), this.firstPageListener);
        } else {
            PaginationUtil.setDisabled($("myspaceFriendsPrevPage"), this.prevPageListener);
            PaginationUtil.setDisabled($("myspaceFriendsFirstPage"), this.firstPageListener);
        }
        
        // only observe first accordion click for getFriends
        Event.stopObserving("link_myspaceFriendsPics", "click", this.getFriendsListener, false);
        Event.stopObserving("myspaceFriendsPicsHeader", "click", this.getFriendsListener, false);
    },
    
    clearContainer: function(container) {
        // clear out old images
        if (container) {
            var des = Element.immediateDescendants(container);
            for(i = 0 ; i < des.length; i++) {
                des[i].remove();
            }
        }
    },

    firstPage: function() {
        if (this.currentPage != 1) {
            this.startProgress();
            this.currentPage = 1;
            this.getFriends();
        }
    },
    
    lastPage: function() {
        if (this.currentPage != this.numPages) {
            this.startProgress();
            this.currentPage = this.numPages;
            this.getFriends();
        }
    },
    
    prevPage: function() {
        if (this.currentPage > 1) {
            this.startProgress();
            this.currentPage -= 1;
            this.getFriends();
        }
    },

    nextPage: function() {
        if (this.currentPage < this.numPages) {
            this.startProgress();
            this.currentPage += 1;
            this.getFriends();
        }
    }
};

RetrieveMyspacePhotos = Class.create();
RetrieveMyspacePhotos.prototype = {
    perpage: global.perpage,
    totalSize: null,
    numPages: null,
    permissionMsg: "Top Pics needs access to your public photos.  Check the box below and continue.",
    
    initialize: function() {
        this.currentPage = 1;
        this.profileUrl = null;
        this.displayName = null;
        this.container = $('containerMyspaceResults');
        this.firstPageListener = this.firstPage.bindAsEventListener(this);
        this.prevPageListener = this.prevPage.bindAsEventListener(this);
        this.nextPageListener = this.nextPage.bindAsEventListener(this);
        this.lastPageListener = this.lastPage.bindAsEventListener(this);
        this.getOwnerPhotos();
    }, 

    getOwnerPhotos: function() {
        this.startProgress();

        var dataReqObj = opensocial.newDataRequest();
        
        var param = {};
        param[opensocial.DataRequest.PeopleRequestFields.FIRST] = ((this.currentPage - 1) * this.perpage) + 1;
        param[opensocial.DataRequest.PeopleRequestFields.MAX] = this.perpage;
        var newReq = dataReqObj.newFetchPhotosRequest(opensocial.DataRequest.PersonId.OWNER, param);
        var newReq2 = dataReqObj.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER, param);
        dataReqObj.add(newReq, "ownerPhotos");
        dataReqObj.add(newReq2, "owner");
        dataReqObj.send(this.photoResponse.bind(this));
    },
    
    photoResponse: function(data) {
        // set profile url and displayname for phobs
        this.profileUrl = data.get("owner").getData().getField("profileUrl");
        this.displayName = data.get("owner").getData().getDisplayName();
        
        var photosRes = data.get("ownerPhotos");
        if(photosRes.hadError()) {
            if (photosRes.getErrorCode() == opensocial.ResponseItem.Error.UNAUTHORIZED) {
                this.requestPhotoPermission();
                return;
                
            }
            new AlertBox({
                style: "error",
                title: global.errorMsg
            });
        }
        var photos = photosRes.getData();
        
        // calculate number of pages based on total number of photos 
        if (this.numPages == null) {
            this.totalSize = photos.getTotalSize();
            this.numPages = Math.ceil(this.totalSize / this.perpage);
        }
        
        if (this.totalSize > 0) {
            // clear old photos
            this.clearPhotos(this.container);
            
            photos.each(function(photoData){
                // use fullsize myspace images for thumb and full
                var photoUri = photoData.getField(MyOpenSpace.Photo.Field.IMAGE_URI);
                var phob = new PhotoObject(photoUri, photoUri, this.profileUrl, this.displayName);
                this.container.appendChild(pageControl.getAddableThumbnailListItem(phob.thumbUrl, Object.toJSON(phob)));
            }.bind(this));
        } else {
            this.clearPhotos(this.container);
            var div = Builder.node('div',
                        {className: "messageText"},
                        global.noimages);
            this.container.appendChild(div);
        }
        
        this.stopProgress();
    },
    
    requestPhotoPermission: function() {
        opensocial.requestPermission(
            ["accesstopublicvideosphotos"],
            this.permissionMsg,
            this.checkPhotoPermissionResponse.bind(this)
        );
    },
    checkPhotoPermissionResponse: function(result) {
        if (result != null && result["accesstopublicvideosphotos"]) {
            this.getOwnerPhotos();
        } else {
            this.clearPhotos(this.container);
            var div = Builder.node(
                        'div',
                        {className: "messageText"},
                        "Public photos permission is restricted!"
                    );
            this.container.appendChild(div);
            var a = Builder.node(
                        "a",
                        {
                            href: "javascript:void(0);",
                            id: "requestPhotoPermission"
                        },
                        "Change my permissions now."
                    );
            this.container.appendChild(a);
            Event.observe("requestPhotoPermission", "click", this.requestPhotoPermission.bindAsEventListener(this), false);
            this.stopProgress();
        }
    },

    startProgress: function() {
        Element.show("myspaceResultsShroud");
        Element.show("myspaceResultsIndicator");
    },
    
    stopProgress: function() {
        Element.hide("myspaceResultsShroud");
        Element.hide("myspaceResultsIndicator");
        // fix pagination buttons
        if (this.currentPage < this.numPages) {
            PaginationUtil.setEnabled($("myspaceResultsNextPage"), this.nextPageListener);
            PaginationUtil.setEnabled($("myspaceResultsLastPage"), this.lastPageListener);
        } else {
            PaginationUtil.setDisabled($("myspaceResultsNextPage"), this.nextPageListener);
            PaginationUtil.setDisabled($("myspaceResultsLastPage"), this.lastPageListener);
        }
        if (this.currentPage > 1) {
            PaginationUtil.setEnabled($("myspaceResultsPrevPage"), this.prevPageListener);
            PaginationUtil.setEnabled($("myspaceResultsFirstPage"), this.firstPageListener);
        } else {
            PaginationUtil.setDisabled($("myspaceResultsPrevPage"), this.prevPageListener);
            PaginationUtil.setDisabled($("myspaceResultsFirstPage"), this.firstPageListener);
        }
    },
    
    clearPhotos: function(container) {
        this.startProgress();
        // clear out old images
        if (container) {
            var des = Element.immediateDescendants(container);
            for(i = 0 ; i < des.length; i++) {
                des[i].remove();
            }
        }
    },

    firstPage: function() {
        if (this.currentPage != 1) {
            this.currentPage = 1;
            this.getOwnerPhotos();
        }
    },
    
    lastPage: function() {
        if (this.currentPage != this.numPages) {
            this.currentPage = this.numPages;
            this.getOwnerPhotos();
        }
    },
    
    prevPage: function() {
        if (this.currentPage > 1) {
            this.currentPage -= 1;
            this.getOwnerPhotos();
        }
    },

    nextPage: function() {
        if (this.currentPage < this.numPages) {
            this.currentPage += 1;
            this.getOwnerPhotos();
        }
    }
};

MySpacePhotoFetcher = Class.create();
MySpacePhotoFetcher.prototype = {
    perpage: global.perpage,
    numPages: null,
    totalSize: null,

    initialize: function(id, name) {
        this.id = id;
        this.name = name;
        this.currentPage = 1;
        this.container = $('containerMyspacePics');
        this.clearPhotos(this.container);
        this.firstPageListener = this.firstPage.bindAsEventListener(this);
        this.prevPageListener = this.prevPage.bindAsEventListener(this);
        this.nextPageListener = this.nextPage.bindAsEventListener(this);
        this.lastPageListener = this.lastPage.bindAsEventListener(this);
        this.friendsBackListener = this.friendsBack.bindAsEventListener(this);
        $("myspaceBack").show();
        Event.observe("friends_back", "click", this.friendsBackListener, false);
        this.getPhotos();
    }, 

    getPhotos: function() {
        this.startProgress();
    
        var params = {
            "action": this.id + "/photos",
            "page": this.currentPage,
            "page_size": this.perpage
        };
        var req = new APIRequest("getmyspacedata", true, params, this.photoResponse.bind(this), this.errorResponse.bind(this), false);
    },

    photoResponse: function(resp) {
        var photos = resp.myspaceresponse.photos;
        
        // calculate number of pages based on total number of photos 
        if (this.numPages == null) {
            this.totalSize = resp.myspaceresponse.count;
            this.numPages = Math.ceil(this.totalSize / this.perpage);
        }
        
        // clear old photos
        this.clearPhotos(this.container);

        if (this.totalSize > 0) {
            photos.each(function(photoData){
                // use fullsize myspace images for thumb and full
                var phob = new PhotoObject(photoData.imageUri, photoData.imageUri, photoData.user.webUri, photoData.user.name);
                this.container.appendChild(pageControl.getAddableThumbnailListItem(phob.thumbUrl, Object.toJSON(phob)));
            }.bind(this));
        } else {
            var div = Builder.node('div',
                        {className: "messageText"},
                        global.noimages);
            this.container.appendChild(div);
        }
        
        this.stopProgress();

    },
    
    errorResponse: function(data) {
        if (data.error) {
            new AlertBox({
                style: "error",
                title: data.error.msg
            });
        }
        this.stopProgress();
        this.friendsBack();
    },

    startProgress: function() {
        Element.show("myspacePicsShroud");
        Element.show("myspacePicsIndicator");
        this.setHeader(this.name + "'s MySpace Pics");
    },
    
    stopProgress: function() {
        Element.hide("myspacePicsShroud");
        Element.hide("myspacePicsIndicator");
        // fix pagination buttons
        if (this.currentPage < this.numPages) {
            PaginationUtil.setEnabled($("myspacePicsNextPage"), this.nextPageListener);
            PaginationUtil.setEnabled($("myspacePicsLastPage"), this.lastPageListener);
        } else {
            PaginationUtil.setDisabled($("myspacePicsNextPage"), this.nextPageListener);
            PaginationUtil.setDisabled($("myspacePicsLastPage"), this.lastPageListener);
        }
        if (this.currentPage > 1) {
            PaginationUtil.setEnabled($("myspacePicsPrevPage"), this.prevPageListener);
            PaginationUtil.setEnabled($("myspacePicsFirstPage"), this.firstPageListener);
        } else {
            PaginationUtil.setDisabled($("myspacePicsPrevPage"), this.prevPageListener);
            PaginationUtil.setDisabled($("myspacePicsFirstPage"), this.firstPageListener);
        }
    },
    
    setHeader: function(txt) {
        $("myspaceFriendsPicsHeader").innerHTML = txt;
    },
    
    friendsBack: function() {
        // hide pics, show friends
        Element.hide("myspacePics");
        Element.show("myspaceFriends");
        this.setHeader("MySpace Friends");
        pageControl.mySpaceFriends.getFriends();
        // stop observing myspace friends pics pagination
        Event.stopObserving("myspacePicsFirstPage", "click", this.firstPageListener, false);
        Event.stopObserving("myspacePicsPrevPage", "click", this.prevPageListener, false);
        Event.stopObserving("myspacePicsNextPage", "click", this.nextPageListener, false);
        Event.stopObserving("myspacePicsLastPage", "click", this.lastPageListener, false);
        Event.stopObserving("friends_back", "click", this.friendsBackListener, false);
    },

    clearPhotos: function(container) {
        this.startProgress();
        // clear out old images
        if (container) {
            var des = Element.immediateDescendants(container);
            for(i = 0 ; i < des.length; i++) {
                des[i].remove();
            }
        }
    },

    firstPage: function() {
        if (this.currentPage != 1) {
            this.currentPage = 1;
            this.getPhotos();
        }
    },
    
    lastPage: function() {
        if (this.currentPage != this.numPages) {
            this.currentPage = this.numPages;
            this.getPhotos();
        }
    },
    
    prevPage: function() {
        if (this.currentPage > 1) {
            this.currentPage -= 1;
            this.getPhotos();
        }
    },

    nextPage: function() {
        if (this.currentPage < this.numPages) {
            this.currentPage += 1;
            this.getPhotos();
        }
    }
};


PageControl = Class.create();
PageControl.prototype = {

    // references to objects
    leftNav : null,
    mySpacePhotos : null,
    mySpaceFriends : null,
    swfGridControl : null,

    // opensocial vars
    isOpensocial : null,
    isMyspace: null,
   
    imgArray: {},

    linkClearAll : null,
    cookieName: "Photobucket-opensocial",
    items: null,
    eltSaveContainer: null,
    eltSaveButton: null,
    owner: null,
    profileId: null,
    profileUrl: null,
    profileLink: null,
    swfPopulated: false,

    initialize: function() {
        this.isOpensocial = (typeof(opensocial) !== 'undefined');
        this.isMyspace = (typeof(MyOpenSpace) !== 'undefined');

        Event.observe(window, 'load', this.pageInit.bindAsEventListener(this));
    },

    pageInit: function(evnt) {
        this.initCanvasView();
        this.swfInit();
    },

    populateSwf: function(profileId) {              
        var params = {"profileId":profileId};
        var req = new APIRequest('saveopensocialstate', true, params, this.handleStateSuccess.bind(this), this.handleStateFailure.bind(this), false, "POST");
    },

    handleStateSuccess: function(data) {
        this.items = data.json;
        if(this.items != null) {
            var count = 0;
            if(!this.swfPopulated && this.swfGridControl != null) {
                this.swfGridControl.prePopulate(this.items);
                this.swfPopulated = true;
            }
        }
    },

    handleStateFailure: function(error) {
        var errorTitle, errorMsg;
        if (error.msg) { // PB API error
            errorTitle = "An error has occurred with Photobucket."
            errorMsg = error.msg;
        } else if (error.errorMessage) { // Myspace proxy error
            errorTitle = "An error has occurred with MySpace."
            errorMsg = error.errorMessage;
        } else if (error.errors && error.errors.length > 0 ) {
            errorTitle = "An error has occurred with MySpace."
            errorMsg = error.errors[0];
        } else {
            errorTitle = global.errorMsg
        }
        new AlertBox({
            style: "error",
            title: errorTitle,
            message: errorMsg
        });

    },

    initCanvasView: function() {
        Element.show('containerCanvas');
        
        // get profile data
        var dataReqObj = opensocial.newDataRequest();
        var params = new Array();
        params[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = [opensocial.Person.Field.GENDER];
        var newReq = dataReqObj.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER, params);
        dataReqObj.add(newReq, "owner");
        dataReqObj.send(function(data){
            this.owner = data.get("owner").getData();
            this.profileId = this.owner.getId();
            this.profileUrl = this.owner.getField("profileUrl");
            this.populateSwf(this.profileId);
        }.bind(this));
        
        this.leftNav = new LeftNav();
        this.recentUserPhotosControl = new RecentUserPhotosControl();
        this.searchPhotosControl = new SearchPhotosControl();
        this.backgroundPhotosControl = new BackgroundPhotosControl();
        this.searchCategoryPhotosControl = new SearchCategoryPhotosControl();
        
        this.linkClearAll = $('linkClearAll');
        Event.observe(this.linkClearAll, 'click', this.handleClearAllClick.bindAsEventListener(this), false);

        this.eltSaveContainer = $('containerSave');
        this.eltSaveButton = $('btnSaveChanges');
        Event.observe(this.eltSaveButton, 'click', this.save.bindAsEventListener(this), false);

        if (this.isOpensocial && this.isMyspace) this.mySpacePhotos = new RetrieveMyspacePhotos();
        if (this.isOpensocial && this.isMyspace) this.mySpaceFriends = new FriendsFetcher();
        
        this.profileLink = $("linkProfile");
        Event.observe("linkProfile", "click", this.save.bindAsEventListener(this), false);

        // TODO: hiding "add more" button for now
        $("myspaceResultsAddMore").hide();
    },

    addToGrid: function(phobString) {
        this.swfGridControl.addItem(phobString);
    },

    fixWidths: function(img, hasTitles) {
        return function (evnt) {
            var width = img.width;
            var height = img.height;

            var li = Element.up(img, 'LI', 0);
            
            if (typeof(li) !== "undefined") {
                var cWidth = li.clientWidth;
                var cHeight = li.clientHeight;
                if (hasTitles) {
                    cWidth = li.clientWidth - 20;
                    cHeight = li.clientHeight - 20;
                }
                var scale = null;
                
                // shrink
                if (width > cWidth || height > cHeight) {
                    if (width < height) {
                        if (width > cWidth) {
                            img.style.width = cWidth;
                            scale = (cWidth / width);
                            height = scale * height;
                            width = cWidth;
                        }
                    }
                    else {
                        if (height > cHeight) {
                            img.style.height = cHeight;
                            scale = (cHeight / height);
                            width = scale * width;
                            height = cHeight;
                        }
                    }
                }
                
                // vertically align:
                var topOffset = (cHeight - height) / 2;
                img.style.top = Math.floor(topOffset);
                
                // horizontally align:
                var leftOffset = (cWidth - width) / 2;
                img.style.left = Math.floor(leftOffset);
                
                img.style.visibility = "visible";
                if (Element.hasClassName(li, 'loading')) 
                    Element.removeClassName(li, 'loading');
            }
        };
    },

    fireMouseEvent: function(elt, strEvent, bubbles, cancelable)
    {   
        var bBubbles = false, bCancelable = true;
        if(typeof(bubbles) == "boolean"){
            bBubbles = bubbles;
        }
        if(typeof(cancelable) == "boolean"){
            bCancelable = cancelable;
        }

        // Note: strEvent = Event name w/o "on" prefix (Ex: "click")
        if(typeof(elt) != "undefined" && elt && typeof(strEvent) == "string" && strEvent.length > 0){
            var objEvnt; // Synthetic Event Obj
            // Sythesize Click event
            if(document.createEvent){       // W3C
                objEvnt = document.createEvent('MouseEvents');
                objEvnt.initEvent(strEvent, bBubbles, bCancelable);
                elt.dispatchEvent(objEvnt);
            }
            else if(document.createEventObject){ // MSIE
                objEvnt = document.createEventObject(); // copy the original event to the new event object
                elt.fireEvent('on' + strEvent, objEvnt);
            }
        }
    },

    // in the left nav
    getAddableThumbnailListItem: function(imgSource, phobString) {
        var li = Builder.node('li', {onClick:"pageControl.addToGrid('"+ phobString +"');"});
        var div = Builder.node('div');

        if (typeof(this.imgArray[imgSource]) == 'undefined') {
            Element.addClassName(li, 'loading');
            this.imgArray[imgSource] = Builder.node('img', {src:imgSource});
            Event.observe(this.imgArray[imgSource], 'load', this.fixWidths(this.imgArray[imgSource]).bindAsEventListener(this), false);
        }
        
        li.appendChild(div);
        li.appendChild(this.imgArray[imgSource]);

        return li;
    },
    
    // in the left nav
    getAddableBackgroundListItem: function(imgSource) {
        var li = Builder.node('li', {onClick:"pageControl.swfGridControl.setBackground('"+ imgSource +"');"});
        var div = Builder.node('div');

        if (typeof(this.imgArray[imgSource]) == 'undefined') {
            Element.addClassName(li, 'loading');
            this.imgArray[imgSource] = Builder.node('img', {src:imgSource});
            Event.observe(this.imgArray[imgSource], 'load', this.fixWidths(this.imgArray[imgSource]).bindAsEventListener(this), false);
        }
        
        li.appendChild(div);
        li.appendChild(this.imgArray[imgSource]);

        return li;
    },
    
    getAddableSearchCategoryListItem: function(searchTerm, imgSource) {
        var li = Builder.node('li', {onClick:"$('query').value='"+searchTerm+"';pageControl.fireMouseEvent($('searchForm'), 'submit', false, true);",
                                    title: "Search for '" + searchTerm + "'"});
        var div = Builder.node('div');
        Element.addClassName(div, "profilepics");
        Element.addClassName(li, "loading");
        var termDiv = Builder.node("div", {className: "blueSubheader"}, searchTerm);
        
        if (typeof(this.imgArray[imgSource]) == 'undefined') {
            this.imgArray[imgSource] = Builder.node('img', {src:imgSource});
            Event.observe(this.imgArray[imgSource], 'load', this.fixWidths(this.imgArray[imgSource]).bindAsEventListener(this), false);
        }

        li.appendChild(div);
        li.appendChild(this.imgArray[imgSource]);
        li.appendChild(termDiv);

        return li;
    },


    getFriendListItem: function(friendData) {
        var li = Builder.node("li", {onclick: "pageControl.fetchFriendPhotos('" + friendData.id + "', '" + friendData.name + "');",
                                    title: friendData.name + "'s MySpace Pics"});
        var div = Builder.node("div");
        Element.addClassName(div, "profilepics");
        Element.addClassName(li, "loading");
        var img = Builder.node("img", {src: friendData.thumbUrl});
        Event.observe(img, 'load', this.fixWidths(img).bindAsEventListener(this), false);
        
        var profilename = friendData.name;
        if (profilename.length > 18) {
            profilename = profilename.substring(0, 15) + "...";
        }
        var nameDiv = Builder.node("div", {className: "blueSubheader"}, profilename);

        li.appendChild(div);
        li.appendChild(img);
        li.appendChild(nameDiv);
        
        return li;
        
    },
    
    fetchFriendPhotos: function(id, name) {
        // hide friends, show pics
        Element.hide("myspaceFriends");
        Element.show("myspacePics");
        this.mySpacePhotos = null;
        this.mySpacePhotos = new MySpacePhotoFetcher(id, name);
    },

    // grid view
    getRemoveableThumbnailListItem: function(imgSource) {
        
        var li = Builder.node('li', {className:"loading"});
        var div = Builder.node('div', {onClick:"pageControl.removeFromGridClick(this);"});

        var img = Builder.node('img', {src:imgSource});
        Event.observe(img, 'load', this.fixWidths(img).bindAsEventListener(this), false);
        
        li.appendChild(div);
        li.appendChild(img);

        return li;
    },

    // grid view
    getStaticThumbnailListItem: function(imgSource) {

        var li = Builder.node('li', {className:"loading"});

        var img = Builder.node('img', {src:imgSource});
        Event.observe(img, 'load', this.fixWidths(img).bindAsEventListener(this), false);
        
        li.appendChild(img);

        return li;
    },

    swfInit: function() {
        var fo = new SWFObject($F('swflocation'),"gridEmbed","420","420","9.0.28");

        fo.useExpressInstall('http://photobucket.com/flash/playerProductInstall.swf');
        fo.addParam("align","middle");
        fo.addParam("quality","high");
        fo.addParam("allowNetworking","all");
        fo.addParam("allowScriptAccess","always");
        fo.addParam("wmode","transparent");
         
        var swfContainer = 'containerGrid';

        if (!fo.write(swfContainer)) {
            $('containerGrid').innerHTML = '<h1 id="flashDetectFailed"><a target="blank" class="link" href="http://www.adobe.com/go/getflashplayer">This application requires Flash 9 or newer.&nbsp;Go to Adobe.com to get it!</a> </h1>';
        }
    },

    handleClearAllClick: function(evnt) {
        pageControl.swfGridControl.clearAllItems();
    },

    save: function(){
        // only save if save button is visible
        // (e.g. checking when user clicks on profile link)
        if ($('containerSave').style.visibility == 'visible') {
            pageControl.swfGridControl.setProfileId(this.profileId);
            data = this.swfGridControl.getData();
            var params = {"data": escape(data)};
            if(typeof(console) !== "undefined") console.log(data);
            var req = new APIRequest('saveopensocialstate', true, params, this.handleSaveSuccess.bind(this), this.handleSaveFailure.bind(this), false, "POST");
        } else {
            this.gotoProfile();
        };
    },

    handleSaveSuccess: function() {
        var saveBtn = $('containerSave');
        if ((saveBtn.style.visibility != "hidden")) {
            this.eltSaveContainer.style.visibility = 'hidden';
            new Effect.Highlight("previewMenu");
        }
        
        new AlertBox({
                type: "confirm",
                title: "Post a Bulletin",
                message: "Would you like to post a bulletin about your updated top pics?"
            },
            this.postBulletin.bind(this),
            this.gotoProfile.bind(this)
        );
        
    },

    handleSaveFailure: function() {
    },
    
    postBulletin: function() {
        var name = this.owner.getDisplayName();
        var gender = this.owner.getField(MyOpenSpace.Person.Field.GENDER);
        var adjective;
        if (gender && gender.toLowerCase() == "male") {
            adjective = "his";
        } else if (gender && gender.toLowerCase() == "female") {
            adjective = "her";
        } else {
            adjective = "their";
        }
        var subject = name + " updated " + adjective + " top pics";
        var content = subject + ".  <a href='" + this.profileUrl + "'>Check out " + adjective + " profile</a> to see if your pics are in there.<br/><br/>" +
            "Get your own top pics at <a href='http://myspace.com/top_pics'>http://myspace.com/top_pics</a>"; 
        var bulletin = opensocial.newMessage(content);
        bulletin.setField(opensocial.Message.Field.TITLE, subject);
        bulletin.setField(opensocial.Message.Field.TYPE, MyOpenSpace.PostTo.Targets.BULLETINS);
        var os_token = MyOpenSpace.MySpaceContainer.OSToken;
        opensocial.Container.get().postTo(os_token, bulletin, this.owner, this.gotoProfile.bind(this));
    },
    
    gotoProfile: function() {
        opensocial.requestNavigateTo(global.profileSurface);
    },
    
    // SWF calls this
    swfLoaded: function() {
        this.swfGridControl = $('gridEmbed');
        
        this.swfGridControl.setPadding('10');
        this.swfGridControl.setMaxItems('16');
        this.swfGridControl.setCellHeight('100');
        this.swfGridControl.setCellWidth('100');
        this.swfGridControl.setCols('4');
        this.swfGridControl.setRows('4');
        this.swfGridControl.displayGrid('canvas');
        if(this.items != null && this.swfGridControl != null && !this.swfPopulated) {
            this.swfGridControl.prePopulate(this.items);
            this.swfPopulated = true;
        }
    },

    // SWF calls this
    swfChanged: function() {
       $('containerSave').style.visibility = 'visible';
    }
    
};
AlertBox = Class.create();
AlertBox.prototype = {
    messagePanel : null,
    overlay: null,
    type: null,
    style: null,
    okButton: null,
    cancelButton: null,
    okCallback: null,
    cancelCallback: null,
    result: null,

    initialize: function(params, okCallback, cancelCallback){
        this.type = params.type;
        this.style = params.style;
        this.messagePanel = $("messagePanel");
        this.overlay = $("overlay");
        this.okCallback = okCallback;
        this.cancelCallback = cancelCallback;
        this.okListener = this.handleOk.bindAsEventListener(this);
        this.cancelListener = this.handleCancel.bindAsEventListener(this);
        var children = this.messagePanel.childElements();
        var header = children[0];
        var para = children[1];
        this.okButton = children[2];
        this.cancelButton = children[3];
        
        if (this.type == "confirm") {
            this.cancelButton.show();
        } else {
            this.cancelButton.hide();
        }
        
        if (this.style == "error") {
            this.messagePanel.addClassName("error");
        } else {
            this.messagePanel.removeClassName("error");
        }
        
        this.overlay.show();
        this.messagePanel.show();
        header.innerHTML = "";
        if (params.title) 
            header.innerHTML = params.title;
        para.innerHTML = "";
        if (params.message) 
            para.innerHTML = params.message;
        
        Event.observe(this.okButton, "click", this.okListener, false);
        Event.observe(this.cancelButton, "click", this.cancelListener, false);
        
    },
    
    handleOk: function() {
        this.dismiss();
        if (this.okCallback) {
            this.okCallback();
        }
    },
    
    handleCancel: function() {
        this.dismiss();
        if (this.cancelCallback) {
            this.cancelCallback();
        }
    },
    
    dismiss: function() {
        this.messagePanel.hide();
        this.overlay.hide();
        Event.stopObserving(this.okButton, "click", this.okListener, false);
        Event.stopObserving(this.cancelButton, "click", this.cancelListener, false);
    }
    
};
    

var pageControl = new PageControl();

