var PageLoader = new Class({
    Implements: Options,

    options: {
        'transitionOptions': {'duration': 500},
        'loadDelay': 250,
        'loadCallback': null,
        'startLoadCallback': null,
        'failureCallback': null,
        'renderedCallback': null,
        'historyKey': 'page',
        'historyRegex': "-([\-\_0-9a-zA-Z]+)",
        'defaultIndex': 0
    },

    pageTracker: null,
    currentPage: null,
    loadTimer: null,
    loadRequest: null,
    history: null,

    pages: {},
    pageNumbers: [],

    initialize: function(destination, options) {
        this.destination = $(destination);
        this.setOptions(options);

        this.historyManager = $$('body')[0].retrieve('historyManager');
        if(this.historyManager) {
            this.history = this.historyManager.register(
                this.options.historyKey, [-1], function(values) {
                    if(values[0] == -1) {
                        if(this.currentPage) {
                            var hash = new Hash(this.pages);
                            this.displayPage(
                                this.pages[hash.getKeys( )
                                    [this.options.defaultIndex]]['url']);
                        }
                        return;
                    }

                    if($type(values[0]) == "number") {
                        var count = 0;
                        for(id in this.pages) {
                            if(count == values[0]) {
                                this.displayPage(this.pages[id]['url']);
                                return;
                            }
                        }
                    } else {
                        for(id in this.pages) {
                            if(this.pages[id]['id'] == values[0]) {
                                this.displayPage(this.pages[id]['url']);
                                return;
                            }
                        }
                    }
                }.bind(this), function(values) {
                    return [this.options.historyKey, "-", values].join('');
                }.bind(this),
                this.options.historyKey+this.options.historyRegex
            );
        }
        if(this.options.GAAccountId && $defined(_gat)) {
            this.tracker = _gat._getTracker("UA-12833290-1");
        }
    },

    addPage: function(url, id, selector, redirect) {
        if(!this.currentPage) this.currentPage = 0;
        var uri = new URI(url);
        this.pages[uri.toString()] = {'url': uri, 'id': id, 'selector': selector,
            'redirect': redirect};
        this.pageNumbers[this.pageNumbers.length] = uri.toString();

        var hash = window.location.hash;
        if(hash) {
            hash = hash.replace("#", "");
            if(hash.match(new RegExp(this.options.historyKey+
                this.options.historyRegex))) {
                    if(hash.match(new RegExp(id+"$"))) {
                        window.location = uri.toString();
                    }
            }
        }

        return uri.toString();
    },
    addPages: function(urls) {
        urls.each(this.addPage);
    },

    displayPage: function(url) {
        var page= this.pages[$type(url) == "number" ? this.pageNumbers[url]:url];
        if(!page) return;
        if(this.currentPage == page['id']) return;
        if(this.loadTimer) $clear(this.loadTimer);
        this.loadTimer=this.loadPage.delay(this.options.loadDelay, this, page);
        
    },
    loadPage: function(page) {
        if(page['redirect']) {
            window.location = page['url'];
            return;
        }
        if(this.options.startLoadCallback) {
            this.options.startLoadCallback.run(page);
        }
        if(this.loadRequest) this.loadRequest.cancel( );
        if(this.tracker) {
            this.tracker._trackPageview(page['url'].toRelative());
        }
        this.loadRequest = new Request.HTML({
            'method': 'get',
            'url': page['url'].toRelative(),
            'onSuccess': function(tree, elements, html, script) {
                this.showPage.delay(400, this, [page, elements, html, script]);
            }.bind(this),
            'onFailure': function(x) {
                if(this.options.failureCallback) {
                    this.options.failureCallback.run([x, this.loadRequest]);
                }
            }.bind(this)
        });
        this.loadRequest.send();
    },
    loadFailed: function(transport) {

        alert(transport.status); 
    },
    showPage: function(page, els, html, script) {
        var count = 0;
        for(id in this.pages) {
            if(page == this.pages[id] || page.id == this.pages[id].id) {
                this.currentPage = page.id ? page.id : count;
                break;
            }
            count += 1;
        }
        if(count >= this.pages.length) count = 0;

        if(this.history) {
            this.history.setValue(0, this.currentPage);
        }

        if(this.options.loadCallback) {
            this.options.loadCallback.run([count, this.currentPage, page]);
        }

        var s = page.selector;
        es = [];
        if(s) {
            els.getElement(s).each(function(e) { if(e) es.push(e); });
        }
        els = es;
        var dest = this.destination;
        var el = dest.clone();
        if(page['id']) el.set('id', page['id']);
        el.setStyle("height", "auto");
        /*el.setStyles({
            "position": "", "display": "", "width": "", "height": "",
            "border": "", "background-image": "", "padding": "", "margin": "",
            "background-color": ""
        });*/
        el.empty();
        els.each(function(e) { e.inject(el); });
        var dims = el.measure(function() { 
            this.inject(dest, 'after');
            var size = this.getDimensions( );
            this.dispose();
            return size;
        });
        el = new Element(el.get('tag'), {
            'class': el.get('class'), 'id': el.get('id')});
        els.each(function(e) { e.inject(el); });        

        var size = dest.getDimensions( );
        dest.getElements("*").set('tween', this.options.transitionOptions);
        dest.getElements("*").tween('opacity', 0);

        (function( ) {
            el.replaces(dest);

            el.getElements("*").set('tween', this.options.transitionOptions);
            el.getElements("*").set('opacity', 0);            

            var delay = 0;
            var f = (function( ) {
                el.getElements("*").tween('opacity', 1);
                if(this.options.renderedCallback) {
                    this.options.renderedCallback.run(
                        [el, count, this.currentPage, page]);
                }
            }.bind(this));

            if(size.x != dims.x || size.y != dims.y) {
                delay = this.options.transitionOptions.delay / 2 || 250;
                el.setStyle("width", size.x);
                el.setStyle("height", size.y);
                el.morph({'width': dims.x, 'height': dims.y});
            } 
            f.delay(delay); 
            this.destination = el;

            //if(window.resetCurves) window.resetCurves( );

        }).delay(this.options.transitionOptions.delay || 500, this);



    }
});

