﻿/// <reference path="jquery-1.3.1-vsdoc.js" />
/// <reference path="Event.js" />
var Browser = $('html').attr('class');
function AltitudeScroller()
{
    function ASView()
    {
    	var useScroller = true;
        var _navigationSelect = new Event("NavigationSelect");
        this.NavigationSelect = _navigationSelect;
        function NavigationItem(pageId)
        {
            //this assumes the pages are in the same order as the navigation...
            var hrefs = $('dl.On').find('a');//this could probably be cleaner: the problem is we connect in a way that assumes the class 'On'
            var el = hrefs.eq(pageId);
            this.el = el;
            this.pageId = pageId;
            var os = pages.eq(pageId).offset();
            this.os = os;
            this.pageEl = pages.eq(pageId);
            el.bind('click', pageId, function(e)
            {
                //somewhere when this event fires we need to prevent the default behavior - see: jquery docs (looks like return false works for now...)
                _navigationSelect.Trigger({ pageIndex: pageId, offsetTop: pages.eq(pageId).offset().top, sender: this });
                //window.location = el.attr('href');
                //if(el.attr('href').split('#').length > 1) return false;
            });
        }
        function GetNavigationItemsFromPages(pages)
        {
            var navItems = [];
            var navItem = null;
           for(i=0;i<pages.length;i++)
           {
               navItem = new NavigationItem(i);
               navItems.push(navItem);
           }
           return navItems;
       }
        function GetPages()
        {
            return $('.page');
        }
        function IsScrolledIntoView(elem, scrollTop)
        {//and over 50% of the screen
            var docViewTop = $(window).scrollTop();
            var windowHeight = $(window).height();
            var docViewBottom = docViewTop + windowHeight;

            var elemTop = $(elem).offset().top;
            var elemBottom = elemTop + $(elem).height();

            return ((elemBottom >= docViewTop + (windowHeight / 2)) && (elemTop <= docViewBottom - (windowHeight / 2)));
        }
        function getMaxScrollHeight(pageHeight)
        {
            var max = 0;
            max = pageHeight - $(window).height();
            return max;
        }
        function UpdateNavigationItems()
        {
            if (navigationItems != null)
            {
                navigationItems = GetNavigationItemsFromPages(GetPages());
            }
        }
        
        var maxScroll;
        var pages;
        var navigationItems;
        this.AltBg = $('.altimeterBg');
        this.OnPageLoadComplete = function() {
        	$('a').removeAttr('name');
        	//fired on page load complete
        	pages = GetPages();
        	navigationItems = GetNavigationItemsFromPages(pages);
        	//todo: make this a little more robust maybe check if its a href of a navitem.
        	var pageHeight = $('.pages').height();
        	var _maxPageHeight = getMaxScrollHeight(pageHeight);
        	maxScroll = pages.eq(pages.length - 1).offset().top + pages.eq(pages.length - 1).height();
        	$(window).scroll(function()//non ie6 [because we are moving the window scroll to the html (see: Base.css)
        	{
        		pageHeight = $('.pages').height();
        		_maxPageHeight = getMaxScrollHeight(pageHeight);
        		maxScroll = pages.eq(pages.length - 1).offset().top + pages.eq(pages.length - 1).height();
        		controller.AltitudeChanged.Trigger({ maxScroll: _maxPageHeight, currentScroll: $(window).scrollTop() });
        		UpdateCurrentPage();
        	});
        	$('html.IE6 body').scroll(function() {
        		controller.AltitudeChanged.Trigger({ maxScroll: _maxPageHeight, currentScroll: $(document.body).scrollTop() });
        		UpdateCurrentPage();
        	});

        	controller.PageChanged.AddHandler(function() {
        		try 
        		{
        			for (i = 0; i < navigationItems.length; i++) {
        				navigationItems[i].el.removeClass('Selected');
        			}
        			if (navigationItems.length > 0) {
        				navigationItems[model.CurrentPage].el.addClass('Selected');
        			} 
        		}
        		catch (e) { }
        	});
        	UpdateCurrentPage();
        	$(window).scroll();
        	$(document.body).scroll();
        	controller.PageChanged.Trigger();
        }
        this.GradientStart = { r: 0, g: 0, b: 0 };
        this.GradientEnd = { r: 0, g: 39, b: 72 };
        //animation
        var _scrolling = false;
        this.ScrollTo = function(y, speed)
        {
            var __defaultSpeed = (Browser == "IE6") ? 2500 : 2800;
            _scrolling = true;
            $("html,body").animate({ scrollTop: y }, ((speed) ? speed : __defaultSpeed), "easeInOutQuint", function()
            {
                _scrolling = false;
            });
        }
        this.ChangeBgColor = function(color)
        {
            $(document.body).css("background-color", color);
        }
        //keeping selected state on scroll event
        function UpdateCurrentPage()
        {
            for (i = 0; i < navigationItems.length; i++)
            {
                if (IsScrolledIntoView(navigationItems[i].pageEl))
                {
                    if (model.CurrentPage != i)
                    {
                        model.CurrentPage = i;
                        controller.PageChanged.Trigger();
                        var currentPageHref = navigationItems[model.CurrentPage].el.attr('href');
                        //todo: deep linking that doesnt create that glitch stopping thing....
                        //how about: this:
                        if (!_scrolling)//if not animating
                        {
                            // specific to address an issue with page refresh when the URL is the same but doesn't match casing
                            // corrects #113
                            if (currentPageHref.indexOf('#') > 0)
                            {
                                var winLocation = window.location.toString();
                                
                                var docLocation = winLocation.substring(winLocation.lastIndexOf('/') + 1);
                                var docLocationNoHashTag = docLocation.substring(0, docLocation.lastIndexOf('#'));
                                
                                var hrefLocationNoHashTag = currentPageHref.substring(0, currentPageHref.lastIndexOf('#'));
                                var hrefLocationHashTag = currentPageHref.substring(currentPageHref.lastIndexOf('#'));
                                
                                if (docLocationNoHashTag.toLowerCase() == hrefLocationNoHashTag.toLowerCase())
                                {
                                    currentPageHref = docLocationNoHashTag + hrefLocationHashTag;
                                }
                            }
                            window.location = (currentPageHref.indexOf('#') > -1) ? currentPageHref : "#";
                        }
                        break;
                    }
                }
            }
        }
    }

    //init
    var view = new ASView();
    $(document).ready(view.OnPageLoadComplete);


    function ASController()
    {
        var _pageChanged = new Event("PageChanged");
        this.PageChanged = _pageChanged;
        function OnNavigationSelect(e)
        {
            //e.args = pageId
            model.SelectedPage = e.args.pageIndex;
            model.CurrentPage = e.args.pageIndex;
            view.ScrollTo(e.args.offsetTop);
        }
        view.NavigationSelect.AddHandler(OnNavigationSelect);
        var _altitudeChanged = new Event("AltitudeChanged");
        this.AltitudeChanged = _altitudeChanged;
        this.GetColorFromAltitudePercentage = function(altitudePercentage)
        {
            var perc = altitudePercentage / 100;
            var rTotal = Math.abs(view.GradientStart - view.GradientEnd); // from 0 - 100 .. |-100| = 100
            var newColor = { r: 0, g: 0, b: 0 };
            if (altitudePercentage < 100)
            {
                for (var i in view.GradientStart)
                {
                    newColor[i] = Math.round(Math.abs(view.GradientStart[i] - view.GradientEnd[i]) * perc);
                }
            }
            else newColor = view.GradientEnd;
            return "rgb(" + newColor.r + "," + newColor.g + "," + newColor.b + ")";
        }
    }
    var controller = new ASController();

    function ASModel()
    {
        this.CurrentPage = 0;
        this.SelectedPage = 0;
        this.AltitudePercent = 100;
        var heightOfBottomImage = 180;//the bg world images height...should put this in the view in the form of a preloader to load the world image and get its height
        function OnAltitudeChanged(e)
        {
            var altPerc = (e.args.currentScroll / (e.args.maxScroll - heightOfBottomImage)) * 100;
            this.AltitudePercent = altPerc;
            //this totally breaks mvc...but this isnt really mvc anyway
            //all this should be in the controller

            if (view.AltBg.css('backgroundImage') == 'none')
            {
                view.ChangeBgColor(controller.GetColorFromAltitudePercentage(altPerc));
            }
            var oppositePercent = Math.abs(this.AltitudePercent);
            oppositePercent = (oppositePercent > 100) ? 100 : oppositePercent;
            view.AltBg.css('background-position', "center " + oppositePercent + "%");
        }
        controller.AltitudeChanged.AddHandler(OnAltitudeChanged);
    }
    var model = new ASModel(); 
}