(function($) {
    var userAgent = navigator.userAgent.toLowerCase();

    $.browser = {
        version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
        safari: /webkit/.test( userAgent ),
        opera: /opera/.test( userAgent ),
        msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
        mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
    };

})(jQuery);

$.extend(Function.prototype, {
    use: function() {
		var method = this, args = Array.prototype.slice.call(arguments), object = args.shift();
		return function() {
			return method.apply(object, args.concat(Array.prototype.slice.call(arguments)));
		}
    },
    useEL: function() {
        var method = this, args = Array.prototype.slice.call(arguments), object = args.shift();
        return function(event) {
            return method.apply(object, [event || window.event].concat(Array.prototype.slice.call(arguments)));
        }
    }
});

$.extend($.Event.prototype, {
    stop: function() {
        this.stopPropagation();
        this.preventDefault();
    }
});

/**
 * Controller
 * Manages the entire application (for the most part)
 */
var Controller = function() {
    this.els = {
        wishForm: $(Controller.selectors.wishForm),
        updateForm: $(Controller.selectors.updateForm),
        shareForm: $(Controller.selectors.shareForm),
        intro: $(Controller.selectors.intro),
        introClose: $(Controller.selectors.introClose),
        wishBtn: $(Controller.selectors.wishBtn),
        updateBtn: $(Controller.selectors.updateBtn)
    };
    
    this.Message = [];
    
    this.wishForm = new Form(this.els.wishForm, true);

    this.stage = new Stage();
    this.wishes = [];
    
    this.stage.load();
 
    if(window.location.hash != '') {
        var id = window.location.hash.match(/id=(\d+)/);
        if(id && id.length) {
            this.getLoadWish(id[1])
        } else {
            var name = window.location.hash.match(/name=([\w]+)/);
            var event = window.location.hash.match(/event=(\d+)/);
            var outcome = window.location.hash.match(/outcome=(\d+)/);
            
            if(name && event && outcome) {
                this.addWish({data: { id: 9999, outcome_id: outcome[1], event_id: event[1], to_name: name[1], from_name: '', i: '1', force: true }});
                setTimeout(function() {
                    this.startTimer();
                }.use(this), 3000);
            }
        }
        
    } else {
        this.getWishes();
        this.startTimer();
    }
    
    $(document).bind('error', this.alertError.useEL(this));
        
    $(document).bind('wish:add', function(event, event2, data) {
        var data = data[0];
        event.data = {
            id: 9999999,
            i: 0,
            force: true,
            event_id: data['data[Message][event_id]'],
            outcome_id: data['data[Message][outcome_id]'],
            to_name: data['data[Message][to_name]'],
            from_name: data['data[Message][from_name]']
        }
        this.addWish(event); 
    }.useEL(this));
};
$.extend(Controller.prototype, {
    getLoadWish: function(id) {
        var self = this;
        $.getJSON('/game/messages/view/'+id, '', function(data, status) {
            switch(status) {
                case 'success':
                    var i = 1;
                    $(data).each(function() {
                        this.Message.i = i;
                        this.Message.force = true;
                        self.addWish({ data: this.Message })
                        i++;
                    });
                break;
            }
        });
        setTimeout(function() {
            this.getWishes();
            this.startTimer();
        }.use(this), 500);
    },
    getWishes: function() {
        var self = this;
        $.getJSON('/game/messages/get_random', '', function(data, status) {
            switch(status) {
                case 'success':
                    var i = 1;
                    $(data).each(function() {
                        this.Message.i = i;
                        self.addWish({ data: this.Message })
                        i++;
                    });
                break;
            }
        });
    },
    startTimer: function() {
        if(this.interval || !!this.interval) { return; }
        var iteration = 0;
        this.interval = setInterval(function() {
            this.getWishes();
            iteration++;
            if(!(iteration % 2)) {
                this.removeWishes(13);
            } else {
                this.removeWishes(9);
            }
        }.use(this), 10000);
    },
    stopTimer: function() {
        clearInterval(this.interval);
        this.interval = false;
    },
    removeWishes: function(num) {
        for(num--; num >= 0; num--) {
            if(this.wishes[num]) {
                this.wishes[num].hide(function() { this.wishes.shift(); }.use(this));
            }
        }
    },
    addWish: function(event) {
        var wish = event.data;
        this.wishes.push(
            new Wish(wish.id, wish.outcome_id, wish.event_id, wish.to_name, wish.from_name, wish.i, wish.force)
        );
    },
    alertError: function(event, event2, message) {
        new ErrorHandler(message);
    }
});
$.extend(Controller, {
    selectors: {
        wishForm: '#wishForm',
        shareForm: '#shareForm',
        updateForm: '#updateBox',
        intro: '#intro',
        introClose: '#intro .close',
        wishBtn: '#intro .wishForm, #sendToFriend',
        updateBtn: '.btn.link.updates',
        wishClose: '#wishForm .close'
    },
    init: function() {
        Controller.instance = new Controller();
    }
});


var ErrorHandler = function() {

    //this.els = {
    //    overlay: $(ErrorHandler.selectors.overlay),
    //    container: $(ErrorHandler.selectors.container)
    //}
    //$.extend(this.els, {
    //    header: this.els.container.find(ErrorHandler.selectors.header).text(this.message.header),
    //    message: this.els.container.find(ErrorHandler.selectors.message).text(this.message.message),
    //    close: this.els.container.find(ErrorHandler.selectors.closeBtn).text(this.message.confirm)
    //});

    //this.els.close.bind('click', this.hide.useEL(this));
    //
    //this.show();
};
$.extend(ErrorHandler.prototype, {
    returnErrors: function(errors) {
        alert(errors.join('\n'))
    },
    setPosition: function() {
        var leftCenter = Math.round(($(window).width()/2)-(this.els.container.width()/2));
        var topCenter = Math.round(($(window).height()/2)-(this.els.container.height()/2));
        
        this.els.container.css({ 'top': topCenter+'px', 'left': leftCenter+'px' });
    },
    show: function() {
        this.setPosition();
        
        this.els.overlay.show().css({'opacity': 0}).animate({ 'opacity': 0.6 }, 500);
   
        if($.support.opacity) {
            this.els.container.fadeIn(500);
        } else {
            this.els.container.show();
        }
    },
    hide: function(event) {
        if(event) { event.stop(); }
        
        this.els.overlay.animate({ 'css': 0 }, 500, function() {
            this.els.overlay.hide();
        }.use(this));
        
        if($.support.opacity) {
            this.els.container.fadeOut(500);
        } else {
            this.els.container.hide();
        }
    }
});
$.extend(ErrorHandler, {
    selectors: {
        overlay: '#overlay',
        container: '#errorBox',
        header: 'h2',
        message: 'p',
        closeBtn: '.btn'
    }
});


/**
 * Generic Form Class
 * Controls positioning, hiding and showing forms.
 */
var Form = function() {
    this.els = {
        container: $(Form.selectors.container)
    };
    
    $.extend(this.els, {
        updaters: this.els.container.find(Form.selectors.updaters),
        preview: {
            to: this.els.container.find(Form.selectors.preview.to),
            from: this.els.container.find(Form.selectors.preview.from),
            event: this.els.container.find(Form.selectors.preview.event),
            outcome: this.els.container.find(Form.selectors.preview.outcome)
        },
        inputs: {
            to: this.els.container.find(Form.selectors.inputs.to),
            toEmail: this.els.container.find(Form.selectors.inputs.toEmail),
            from: this.els.container.find(Form.selectors.inputs.from),
            fromEmail: this.els.container.find(Form.selectors.inputs.fromEmail),
            event: this.els.container.find(Form.selectors.inputs.event),
            outcome: this.els.container.find(Form.selectors.inputs.outcome)
        },
        icon: this.els.container.find(Form.selectors.icon),
        overlay: this.els.container.find(Form.selectors.overlay),
        successMessage: this.els.container.find(Form.selectors.successMessage),
        errorMessage: this.els.container.find(Form.selectors.errorMessage)
    });
    
    this.els.successMessage.bind('click', this.resetForm.useEL(this));
    this.els.overlay.bind('click', this.resetForm.useEL(this));

    this.els.updaters.bind('change', this.updatePreview.useEL(this));
    this.els.container.bind('submit', this.submit.useEL(this));
};
$.extend(Form.prototype, {
    updatePreview: function(event) {
        var newTo = this.els.inputs.to.val() || '[to]';
        this.els.preview.to.text(newTo);
        var newFrom = this.els.inputs.from.val() || '[from]';
        this.els.preview.from.text(newFrom);
        this.els.preview.event.text($(this.els.inputs.event.find('option')[this.els.inputs.event.val()-1]).text());
        this.els.preview.outcome.text($(this.els.inputs.outcome.find('option')[this.els.inputs.outcome.val()-1]).text() + '.');
        this.els.icon.attr('src', Wish.outcomeMappings[this.els.inputs.outcome.val()-1].icon);
    },
    submit: function(event) {
        event.preventDefault();
        event.stopPropagation();
        
        var postData = this.els.container.serialize();
        
        if(this.errorCheck()) {
            $.ajax({
                url: this.els.container.attr('action'),
                data: postData,
                type: 'post',
                success: function(data) {
                    var data = {};
                    $(this.els.container.serializeArray()).each(function() {
                        data[this.name] = this.value;
                    });
                    $(document).trigger('wish:add', [[data]]);
                    this.showMessage('success');
                }.use(this),
                error: function(data) {
                    this.showMessage('error');
                }.use(this)
            });
        }
    },
    errorCheck: function() {
        var errors = [];
        
        if(this.checkName(this.els.inputs.from.val())) {
            errors.push('Please enter a first name only for your name.');
        }
        
        if(!this.checkEmail(this.els.inputs.fromEmail.val())) {
            errors.push('The email address you entered for yourself is invalid.')
        }
        
        if(this.checkName(this.els.inputs.to.val())) {
            errors.push('Please enter a first name only for your friend\'s name.');
        }
 
        if(!this.checkEmail(this.els.inputs.toEmail.val())) {
            errors.push('The email address you entered for your friend is invalid.')
        }
        
        if(errors.length) {
            var e = new ErrorHandler();
            e.returnErrors(errors)
            return false;
        } else {
            return true;
        }
    },
    checkEmail: function(value) {
        return /^[\w.!\#$%&\'*+-/=?^_`{|}~]+@([\d.]+|([^\s]+\.+[a-z]{2,6}))$/.test(value);
    },
    checkName: function(value) {
        return (/^\s*$/.test(value)) || (/\s/.test(value));
    },
    showMessage: function(type) {
        this.els.overlay.css({'display': 'block', 'opacity': 0}).fadeTo('slow', 0.8);
        switch(type) {
            case 'success':
                if($.support.opacity) {
                    this.els.successMessage.fadeIn(500);
                } else {
                    this.els.successMessage.show();
                }
            break;
            case 'error':
                if($.support.opacity) {
                    this.els.errorMessage.fadeIn(500);
                } else {
                    this.els.errorMessage.show();
                }
            break;
        }
    },
    resetForm: function() {
        if($.support.opacity) {
            this.els.overlay.fadeOut(500);
            this.els.successMessage.fadeOut(500);
        } else {
            this.els.overlay.hide();
            this.els.successMessage.hide();
        }
    }
});
$.extend(Form, {
    selectors: {
        container: '#MessageAddForm',
        updaters: 'input, select',
        preview: {
            to: '.toName',
            from: '.fromName',
            event: '.event',
            outcome: '.outcome'
        },
        inputs: {
            to: '#MessageToName',
            toEmail: '#MessageToEmail',
            from: '#MessageFromName',
            fromEmail: '#MessageFromEmail',
            event: '#MessageEventId',
            outcome: '#MessageOutcomeId'
        },
        icon: '#iconPreview',
        overlay: '#overlay',
        successMessage: '#successMessage',
        errorMessage: '#errorMessage'
    },
    strings: {
        submitError: {
            header: 'Error sending message',
            message: 'Please fill in all form fields and make sure they are correct.',
            confirm: 'Double Check'
        }
    },
    init: function() {
        Form.instance = new Form();
    }
});

/**
 * Image Preloader
 * Accepts a single or array of image source strings, preloads them and fires events.
 */
var Preloader = function(overlay) {
    this.cache = [];
    this.loading = false;
    
    if(overlay) {
        this.els = {
            overlay: $(Preloader.selectors.overlay),
            container: $(Preloader.selectors.loadingBox),
            stage: $(Preloader.selectors.stage)
        };
        
        $(document).bind('stage:ready', this.hide.useEL(this));
        
        this.show();
    }
};
$.extend(Preloader.prototype, {
   _load: function(source) {
       //if($.inArray(source, this.cache)) {
       //    $(this).trigger('loaded');
       //    return;
       //}
       
       var image = new Image();
       
       image.onload = function() {
           this.cache.push(image.src);
           $(this).trigger('loaded');
       }.use(this);
       
       image.onerror = function() {
           $(document).trigger('error', {image: source});
       }.use(this);
       
       this.loading = true;
       
       $(this).trigger('loading', {image: source});
       
       image.src = source;
   },
   load: function(sources) {
       var sources = $.makeArray(sources);
              
       var preCacheLength = this.cache.length;
       var l = sources.length;
              
       $(this).bind('loaded', function(event) {
           if(sources.length+preCacheLength == this.cache.length) {
               $(this).trigger('complete');
           }
       }.useEL(this));
       
       //$(this).bind('error', function(event) {
       //    $(document).trigger('error', {message: Preloader.strings.error})
       //}.useEL(this));
       
       while(l--) {
           this._load(sources[l]);
       }
   },
   setPosition: function() {
       var leftCenter = Math.round((this.els.stage.width()/2)-(this.els.container.width()/2));
       var topCenter = Math.round((this.els.stage.height()/2)-(this.els.container.height()/2));
       
       this.els.container.css({ 'top': topCenter+'px', 'left': leftCenter+'px' });
   },
   show: function() {
       //this.els.overlay.show();
       this.setPosition();
       this.els.container.show();
   },
   hide: function() {
       setTimeout(function() {
           //this.els.overlay.fadeOut(2000)
           if($.support.opacity) {
               this.els.container.fadeOut(2000)
           } else {
               this.els.container.hide()
           }
       }.use(this), Preloader.minTimeout);
   }
});
$.extend(Preloader, {
    strings: {
        error: 'Error loading images. Please reload this page to try again.'
    },
    selectors: {
        overlay: '#overlay',
        loadingBox: '#loadingBox',
        stage: '#stagecontainer' 
    },
    minTimeout: 1000,
    init: function() {
        Preloader.instance = new Preloader(true);
    }
});

/**
 * Wish
 * Each instance of a wish from the database
 * @param id        {number}    Used to differentiate elements by HTML ID attribute.
 * @param icon      {string}
 * @param message   {string}
 * @param toName    {string}
 * @param fromName  {string}
 * @param loadNum   {number}    Used to determine how long until the icon will fade in.
 */
var Wish = function(id, outcome_id, event_id, toName, fromName, loadNum, force) {
    var now = new Date();
    this.origID = id;
    this.id = id+now.valueOf();
    this.container = $(Wish.selectors.container);
    this.outcome = outcome_id - 1;
    this.event = event_id;
    this.names = { to: toName, from: fromName };
    this.loadNum = loadNum;
    this.forceCenter = force;
    this.icon = Wish.outcomeMappings[this.outcome].icon;
    
    this.load();
};
$.extend(Wish.prototype, {
    load: function() {
        var p = new Preloader();
        
        $(p).bind('complete', this.show.useEL(this));
        
        p.load(this.icon);
    },
    show: function() {
        var image = new Image();
        image.src = this.icon;
        $(image).attr('id', 'wish'+this.id).addClass('icon' + Math.round(this.id % 6));
        
        var location = (!this.forceCenter) ? Controller.instance.stage.getRandomLocation(image.width) : Controller.instance.stage.getCenter(image.width);
        
        setTimeout(function() {
            this.container.append(image);
            
            if($.support.opacity) {
                this.el = $('#wish'+this.id).css({ top: location.top+'px', left: location.left+'px', opacity: 0 }).animate({ top: location.top+20+'px', opacity: 1 }, 1000, 'easeOutSine', function() {
                    if(this.forceCenter) {
                        this.toggleInfoWindow();
                    }
                }.use(this));
            } else {
                this.el = $('#wish'+this.id).css({ top: location.top+'px', left: location.left+'px' }).hide().animate({ top: location.top+20+'px' }, 1000, 'easeOutSine').show();
                if(this.forceCenter) {
                    this.toggleInfoWindow();
                }
            }
            
            this.el.bind('click', this.toggleInfoWindow.useEL(this))
                   .bind('mouseover', this.dummy.useEL(this))
                   .bind('mouseout', this.dummy.useEL(this));
        }.use(this), this.loadNum*1000);
        
    },
    hide: function(callback) {
        var callback = (callback) ? callback : function() {};
        if(this.infoWindow && this.infoWindow.visible) { return; } else {
            if(!this.el) {
                return;
            }
            setTimeout(function() {
                if(this.infoWindow) { this.infoWindow.kill(); }
                var newTop = (this.el.css('top')) ? parseInt(this.el.css('top').replace('px', ''), 10)+20 : 0;
                
                function endAnimation() {
                    this.el.remove();
                    callback();
                }
                
                if($.support.opacity) {
                    this.el.animate({ top: newTop+'px', opacity: 0 }, 500, 'easeInSine', endAnimation.use(this));
                } else {
                    this.el.animate({ top: newTop+'px' }, 500, 'easeInSine', endAnimation.use(this)).hide();
                }
                
            }.use(this), this.loadNum*1000);
        }
    },
    toggleInfoWindow: function() {
        if(!this.infoWindow) { 
            var left = this.el.css('left').replace('px', '');
            var top = this.el.css('top').replace('px', '');
            this.infoWindow = new InfoWindow({
                topOffset: top, leftOffset: left, 
                width: this.el.width(), height: this.el.height()
            }, {id: this.id, origID: this.origID, outcome: Wish.outcomeMappings[this.outcome].text, event: Wish.events[this.event-1].text, names: this.names}); 
        }
        
        this.infoWindow.toggle();
    },
    dummy: function() {
        
    }
});
$.extend(Wish, {
    selectors: {
        container: '#wishes'
    },
    outcomeMappings: [
        { text: 'got carried away by mosquitos', icon: '/images/icon-moquitos.png' },
        { text: 'got pregnant with triplets', icon: '/images/icon-baby.png' },
        { text: 'had visible heart trouble', icon: '/images/icon-fix.png' },
        { text: 'got a concussion, maybe two', icon: '/images/icon-bump.png' },
        { text: 'snapped, crackled and popped', icon: '/images/icon-repair.png' },
        { text: 'dislodged a Deep Vein Thrombus resulting in a Pulmonary Embolism', icon: '/images/icon-clot.png' },
        { text: 'ended up in the market for a new hip', icon: '/images/icon-replace.png' },
        { text: 'ended up feeling a quart low', icon: '/images/icon-dipstick.png' },
        { text: 'got two shiners and some free dental work', icon: '/images/icon-shiners.png' },
        { text: 'won&rsquo;t be giving any high fives for a while', icon: '/images/icon-heal.png' },
        { text: 'dropped a quick five pounds', icon: '/images/icon-5pounds.png' },
        { text: 'turned blue. Or is that pinkish gray?', icon: '/images/icon-blue.png' },
        { text: 'ended up really really regretting that decision', icon: '/images/icon-operate.png' },
        { text: 'ended up feeling a little flat. Actually looking a little flat', icon: '/images/icon-flat.png' },
        { text: 'made an unplanned blood donation', icon: '/images/icon-blood.png' },
        { text: 'ended up missing a few digits', icon: '/images/icon-digits.png' },
        { text: 'got tired. Mostly across the back, a little on the right cheek', icon: '/images/icon-flat.png' },
        { text: 'won&rsquo;t be wearing that shirt any more', icon: '/images/icon-shirt.png' }
    ],
    events: [
        { text: 'picked a fight with the wrong Wild player' },
        { text: 'fell off the giant slide at the state fair' },
        { text: 'should have read the instructions for that new turkey deep fryer' },
        { text: 'tried ice skating for the first time at Rice Park' },
        { text: 'tried out for the Minnesota Roller Girls' },
        { text: 'ate 5 Coney Islands at the Gopher Bar' },
        { text: 'wore a Sioux Falls jersey to a St. Paul Saints game' },
        { text: 'stood up on the roller coaster at Valley Fair' },
        { text: 'texted while driving riding a scooter on University Ave.' },
        { text: 'took a dare to eat 4 lbs. of peanut butter' },
        { text: 'should have known there were snapping turtles in Lake Nokomis' },
        { text: 'got vertigo at the IMAX and fell down the steps' },
        { text: 'stepped in front of the beverage cart on the 9th hole at Como' },
        { text: 'fell skateboarding down Kellogg Blvd in St. Paul' },
        { text: 'got carried away at Grand Ol&rsquo; Days' },
        { text: 'wore red and white to the Gophers&rsquo; Homecoming game' },
        { text: 'tried to taste it all at Taste of Minnesota' },
        { text: 'taunted the tigers at the Como Zoo' },
        { text: 'didn&rsquo;t look both ways crossing 7th Street' }
   ]
});

/**
 * InfoWindow
 */
var InfoWindow = function(dimensions, data) {
    this.data = data;
    this.dimensions = dimensions;
    this.els = {
        container: $(InfoWindow.selectors.container).clone().attr('id', 'wish'+this.data.id).hide().appendTo('#content')
    };
    $.extend(this.els, {
        content: this.els.container.find(InfoWindow.selectors.content),
        closeBtn: this.els.container.find(InfoWindow.selectors.closeBtn),
        sendBtn: this.els.container.find(InfoWindow.selectors.sendBtn),
        nameTo: this.els.container.find(InfoWindow.selectors.nameTo),
        nameFrom: this.els.container.find(InfoWindow.selectors.nameFrom),
        message: this.els.container.find(InfoWindow.selectors.message),
        scrollElement: $(InfoWindow.selectors.stage)
    });

    this.position = dimensions;
    this.visible = false;
    this.populateData();
};
$.extend(InfoWindow.prototype, {
    toggle: function() {
        if(!this.visible) {
            this.show();
            //if(pageTracker) {
            //    pageTracker._trackPageview('/wishes/view/'+this.data.origID);
            //}
        } else {
            this.hide();
        }
    },
    setPosition: function() {
        var topOffset = parseInt(this.dimensions.topOffset, 10) + this.dimensions.height - 20;
        var leftOffset = parseInt(this.dimensions.leftOffset, 10) - this.els.scrollElement.scrollLeft() - (this.els.container.width() - this.dimensions.width / 2) + (this.els.container.width() / 2);

        if(this.els.container.height()+topOffset >= this.els.scrollElement.scrollTop()+$(window).height()) {
            topOffset = topOffset-this.els.container.height()+this.dimensions.height;
        }
        
        if(this.els.container.width()+leftOffset >= this.els.scrollElement.scrollLeft()+$(window).width()) {
            leftOffset = leftOffset-this.els.container.width()+this.dimensions.width;
        }
        
        this.els.container.css({ left: leftOffset+'px', top: topOffset+'px' });
    },
    populateData: function() {
        this.els.message.html(this.data.event+ ' and ' + this.data.outcome);
        this.els.nameTo.html(this.data.names.to);
        this.els.message.attr('value', this.data.message);
    },
    show: function() {
        $(document).trigger('showWindow');
        this.setPosition();
        
        var callback = function() {
            this.visible = true;
            $(document).bind('showWindow', this.hide.useEL(this));
            this.els.closeBtn.bind('click', this.hide.useEL(this));
        }.use(this);
        
        if($.support.opacity) {
            this.els.container.fadeIn(500, callback.use(this));
        } else {
            this.els.container.show();
            callback();
        }
        
    },
    hide: function(event) {
        if(event) { event.stop(); }
        
        var callback = function() {
            this.els.container.hide();
            this.visible = false;
        }.use(this);
        
        if($.support.opacity) {
            this.els.container.fadeOut(500, callback.use(this));
        } else {
            this.els.container.hide();
            callback();
        }
    },
    kill: function() {
        if(!this.visible) {
            this.els.container.remove();
        } else {
            return false;
        }
    }
});
$.extend(InfoWindow, {
    selectors: {
        container: '#infoWindow',
        content: '.content',
        closeBtn: '.close',
        sendBtn: '.send',
        nameTo: '.to',
        nameFrom: '.from',
        message: '.message',
        stage: '#stagecontainer'
    }
})

/**
 * Stage
 * Controls the parallax effects
 */
var Stage = function() {
    this.els = {
        container: $(Stage.selectors.container),
        leftBtn: $(Stage.selectors.leftBtn),
        rightBtn: $(Stage.selectors.rightBtn),
        scrollElement: $(Stage.selectors.scrollElement)
    };
    
    this.layers = [];
    
    this.setSize();
    
    //if(!$.support.opacity) {
    //    this.els.leftBtn.hide();
    //    this.els.rightBtn.hide();
    //} else {
        this.els.leftBtn.bind('click', this.panLeft.useEL(this));
        this.els.rightBtn.bind('click', this.panRight.useEL(this));
        $(document).bind('keydown', this.keyHandler.useEL(this));
    //}
    
    $(document).bind('form:show', this.disablePanButtons.useEL(this));
    $(document).bind('form:hide', this.enablePanButtons.useEL(this));
};
$.extend(Stage.prototype, {
    keyHandler: function(event) {
        switch(event.keyCode) {
            case 37:
                if(this.ablePanLeft) {
                    this.panLeft(event);
                }
            break;
            case 39:
                if(this.ablePanRight) {
                    this.panRight(event);
                }
            break;
        }
    },
    load: function() {
        var loader = new Preloader();
        var sources = $.map(Stage.layers, function(i) { return i.src; });
        
        $(loader).bind('complete', this.appendToEls.useEL(this));
        
        loader.load(sources);
    },
    appendToEls: function() {
        var self = this;
        $(Stage.layers).each(function() {
            self.els.container.append('<div id="'+this.id+'" style="background-image: url('+this.src+');"></div>');
            //$('#'+this.id).css({ backgroundPosition: '(0px 0px)'});
            self.layers.push(this);
        });
        $(document).trigger('stage:ready');
    },
    show: function() {
        this.els.container.fadeIn(500);
    },
    getRandomLocation: function(offset) {
        var offset = (offset) ? offset : 0;
        var width = this.els.container.width();
        var height = this.els.container.height();
        
        var leftOffset = Math.round(width*(Math.random()));
        leftOffset = (leftOffset+(offset*2) > width) ? leftOffset-(offset) : leftOffset;
        leftOffset = (leftOffset-offset < 0) ? leftOffset+offset : leftOffset;
        leftOffset = (leftOffset < Stage.iconPadding.left) ? Stage.iconPadding.left+leftOffset : leftOffset;
        leftOffset = (leftOffset > width+Stage.iconPadding.right) ? leftOffset-Stage.iconPadding.right : leftOffset;
        
        var topOffset = Math.round(height*(Math.random()));
        topOffset = (topOffset+offset > height) ? topOffset-(offset) : topOffset;
        topOffset = (topOffset < 0) ? topOffset+offset : topOffset;
        topOffset = (topOffset < Stage.iconPadding.top) ? Stage.iconPadding.top+topOffset : topOffset;
        topOffset = (topOffset+offset+Stage.iconPadding.bottom >= height-Stage.iconPadding.bottom) ? height - Stage.iconPadding.bottom - offset : topOffset;
        
        return { left: leftOffset, top: topOffset };
    },
    getCenter: function(offset) {
        var windowCenterLeft = Math.round(this.els.scrollElement.width()/2)+this.els.scrollElement.scrollLeft()-Math.round(offset/2);
        var windowCenterTop  = Math.round(this.els.scrollElement.height()/2)+this.els.scrollElement.scrollTop()-offset;
        
        return { left: windowCenterLeft, top: windowCenterTop };
    },
    setSize: function(event) {
        if($.browser.msie) { } else {
            this.els.container.width(this.els.container.width() * Stage.stops);
            this.togglePanButtons();
        }
    },
    panLeft: function(event) {
        event.stop();
        this.els.leftBtn.unbind('click').bind('click', function(event) { event.stop(); });
        var leftPos = Math.floor(this.els.scrollElement.scrollLeft()-($(window).width()/2));
        this.pan(leftPos);
    },
    panRight: function(event) {
        event.stop();
        this.els.rightBtn.unbind('click').bind('click', function(event) { event.stop(); });
        var leftPos = Math.ceil(this.els.scrollElement.scrollLeft()+($(window).width()/2))-1;
        this.pan(leftPos);
    },
    pan: function(leftPos) {
        $(document).trigger('showWindow');
        this.scrollLeft = this.els.scrollElement.scrollLeft();
        this.panTimer = setInterval(function() {
            this.parallax();
        }.use(this), 50);
        this.els.scrollElement.animate({ scrollLeft: leftPos+'px' }, 2000, 'easeInOutSine', function() {
            this.togglePanButtons();
            clearInterval(this.panTimer);
        }.use(this));
    },
    disablePanButtons: function(override) {
        if(this.els.scrollElement.scrollLeft()+$(window).width() >= this.els.container.width()-($(window).width()/3) || override) {
            this.ablePanRight = false;
            if($.support.opacity)  {
                this.els.rightBtn.fadeOut(500);
            } else {
                this.els.rightBtn.hide();
            }
        }
        if(this.els.scrollElement.scrollLeft() <= 0 || override) {
            this.ablePanLeft = false;
            if($.support.opacity)  {
                this.els.leftBtn.fadeOut(500);
            } else {
                this.els.leftBtn.hide();
            }
        }
    },
    enablePanButtons: function() {
        if(this.els.scrollElement.scrollLeft()+$(window).width() < this.els.container.width()-($(window).width()/3)) {
            this.ablePanRight = true;
            if($.support.opacity)  {
                this.els.rightBtn.fadeIn(500).bind('click', this.panRight.useEL(this));
            } else {
                this.els.rightBtn.show().bind('click', this.panRight.useEL(this));
            }
        }
        if(this.els.scrollElement.scrollLeft() > 0) {
            this.ablePanLeft = true;
            if($.support.opacity)  {
                this.els.leftBtn.fadeIn(500).bind('click', this.panLeft.useEL(this));
            } else {
                this.els.leftBtn.show().bind('click', this.panLeft.useEL(this));
            }
        }
    },
    togglePanButtons: function() {
        this.disablePanButtons();
        this.enablePanButtons();
    },
    parallax: function() {
        var scrollLeft = this.els.scrollElement.scrollLeft();
        var diff = this.scrollLeft-scrollLeft;
        $(this.layers).each(function() {
            var el = $('#'+this.id);

            var leftPos = (el.css('backgroundPosition')) ? parseInt(el.css('backgroundPosition').split(' ')[0], 10) : Number(0);
            $('#'+this.id).css({'backgroundPosition': (Math.ceil(diff*this.speed)-diff)+leftPos+'px 0px' });
        });
        this.scrollLeft = this.els.scrollElement.scrollLeft();
    }
});
$.extend(Stage, {
    layers: [
        { id: 'containerBG', src: '/game/css/images/background.gif', speed: 0.7 }
   ],
    selectors: {
        container: '#stage',
        leftBtn: '#stageLeft',
        rightBtn: '#stageRight',
        scrollElement: '#stagecontainer'
    },
    iconPadding: {
        top: 10,
        right: 10,
        bottom: 30,
        left: 10
    },
    stops: 3
});

$(document).ready(function() {
    Preloader.init();
    Controller.init();
    
    $('.submit').attr('value', '');
});