/* 
 * Copyright (c) 2007, ryybo interactive
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 
 * Redistributions in binary form must reproduce the above copyright notice, this
 * list of conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.
 * 
 * Neither the name of the ryybo interactive nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

var ryybo = {};
ryybo.code = {};


/*
 * Page
 */
ryybo.code.Page = function(name, options) {
    $.extend(this, options);
    this.name = name;
};
ryybo.code.Page.prototype.unload = function(callback) {
    if ($.isFunction(this.onPageUnload)) {
        this.onPageUnload(this, callback);
    }
};
ryybo.code.Page.prototype.load = function(callback) {
    if ($.isFunction(this.onPageLoad)) {
        this.onPageLoad(this, callback);
    }
};

/*
 * PageManager
 */
ryybo.code.PageManager = function(pages, options) {
    // merge the passed in options with the defaults
    this.options = $.extend({
        currentPageIndex: 0
    }, options);

    this.pageIndexesByName = {};
    this.pagesByIndex = [];
    this.pagesByName = {};
    this.currentPageIndex = this.options.currentPageIndex;
    this.firstLoad = true;
    this.pageCount = pages.length;
    
    var self = this;
    $.each(pages, function(index) {
        self.pagesByIndex[index] = this;
        self.pagesByName[this.name] = this;
        self.pageIndexesByName[this.name] = index;
    });

    // register the YUI::History manager
    var bookmarkedState = YAHOO.util.History.getBookmarkedState("page"); 
    var initialState = bookmarkedState || 'home';
    YAHOO.util.History.register("page", initialState, this.stateChangeHandler, this);

    YAHOO.util.History.onReady(function() {
      var currentState = YAHOO.util.History.getCurrentState("page");

      self.__gotoPage__(self.pagesByName[currentState]);

      if ($.isFunction(self.options.onReady)) {
        self.options.onReady()
      }
    });

    YAHOO.util.History.initialize("yui-history-field", "yui-history-iframe");
};
//
// This is the YUI history state change handler... this is called whenever the state of the YUI history is changed...
// It simply calls the internal __gotoPage__ method which actually loads the page.
//
ryybo.code.PageManager.prototype.stateChangeHandler = function(state, self) {
	if (self.getPage(state) != null) {
    self.__gotoPage__(self.pagesByName[state]);	
	}
	else {
    self.gotoPage(0);
	}
};

//
// Query methods
//
ryybo.code.PageManager.prototype.getPage = function(page) {
    if (typeof page == 'number') {
        return this.pagesByIndex[page];
    } else if (typeof page == 'string') {
        return this.pagesByName[page];
    }
	else if (page == null) {
		return this.pagesByName['home'];
	}
};

ryybo.code.PageManager.prototype.getPageNameIndex = function(page) {
	return this.getPage(page).name;
}
	
ryybo.code.PageManager.prototype.getPageIndex = function(page) {
    if (page == undefined) {
        page = this.getCurrentPage();
    } else if (typeof page == 'number' || typeof page == 'string') {
        page = this.getPage(page);
    }

    return this.pageIndexesByName[page.name];
};
ryybo.code.PageManager.prototype.getCurrentPage = function() {
    return this.pagesByIndex[this.currentPageIndex];
};
ryybo.code.PageManager.prototype.getPreviousPage = function() {
    var pageIndex = this.currentPageIndex - 1;
    if (pageIndex < 0) pageIndex = this.pageCount - 1;
    return this.pagesByIndex[pageIndex];
};
ryybo.code.PageManager.prototype.getNextPage = function() {
    var pageIndex = this.currentPageIndex + 1;
    if (pageIndex >= this.pageCount) pageIndex = 0;
    return this.pagesByIndex[pageIndex];
};

//
// Navigation methods
//
ryybo.code.PageManager.prototype.previousPage = function() {
    this.gotoPage(this.getPreviousPage().index);
};
ryybo.code.PageManager.prototype.nextPage = function() {
    this.gotoPage(this.getNextPage().index);
};
//
// Goto page simply calls the YAHOO.util.History method with the page name of the passed in page
//
ryybo.code.PageManager.prototype.gotoPage = function(page) {
    // get the page name
    var page_name;
    
    if (typeof page == 'number') {
        if (page > this.pageCount - 1) {
            page = this.pageCount - 1;
        } else if (page < 0) {
            page = 0;
        }
        page_name = this.pagesByIndex[page].name;
    } else if (typeof page == 'string') {
        page_name = this.pagesByName[page].name;
    } else {
        // we have a page object
        page_name = page.name;
    }
    
    YAHOO.util.History.navigate("page", page_name);
};

ryybo.code.PageManager.prototype.__gotoPage__ = function(page) {
    if (! this.firstLoad && page === this.getCurrentPage()) {
        return;
    }

    var self = this;
    var onUnload = function() {
        page.load(function() {
            self.currentPageIndex = self.pageIndexesByName[page.name];
            if ($.isFunction(self.options.onPageChange)) {
                self.options.onPageChange(self, page);
            }
        });
    };

    if (this.firstLoad) {
        onUnload();
        this.firstLoad = false;
		preloadDone = true;
    } else {
        this.getCurrentPage().unload(onUnload);
    }
};