function Springboard()
{
    try
    {
        this.hints = [];
        //this.hints = ["This is the springboard", "Shake to return to springboard", "Swipe to change feature pages", "Touch an icon to display feature"];
        /* Delay before starting hints showing again - default to every 2 minutes */
        this.hintsAgainDelay = 120000;
        this.debug = false;
        this.messageSpeed = 5000;
        this.orientationCheckInterval = 500;
        this.activeLayoutCssIndex = 3;
        this.appName = "Loading...";
        this.pageShowLeft = "0px";
        this.pageHideLeft = "320px";
        this.orientation = 0;
        this.pageOn = '<div id="pageon"><img id="pageonimg" src="css/images/adf.nativeframework.springboard.currentpage.png" alt=""></div>';
        this.pageOff = '<div id="pageoff"><img id="pageoffimg" src="css/images/adf.nativeframework.springboard.otherpage.png" alt=""></div>';
        this.alternateFakeRight = true;
        this.alternateFakeLeft = true;
        this.currentPage = 1;
        this.previousPage = 1;
        this.hideAnimation = "hideToLeft";
        this.showAnimation = "showFromLeft";
        this.hideOpacity = "0.0";
        this.showOpacity = "1.0"
        this.maxPages = 9;
        this.pageCount = 1;
        this.minimumSwipeLength = 110;
        this.pageTransitionSpeed = 320;
        this.startTouch = {x:0,y:0,active:false};
        this.endTouch = {x:0,y:0,active:false};
        this.endTouch.x = 0;
        this.endTouch.y = 0;
        this.endTouch.active = false;  
        this.messageQueue = new Array()
        this.activeHints = [];
        this.isLoaded = false;
    }
    catch(e)
    {
        alert("in Springboard() ERROR:" + e);
    }
}
if (typeof navigator.springboard == "undefined") navigator.springboard = new Springboard();
if (typeof adf == "undefined") adf = {};
if (typeof adf.sb == "undefined") adf.sb = navigator.springboard;

var waitRotation = 0;
var featureList = null;
var iconLoadIndex = 0;
var currentLoadIconFeatureId;
var NO_NEXT_SPRINGBOARD_VISIBLE_FEATURE = 9999;


/**
 * Allows the show of a particular page
 */
function showPage(newPage)
{
    if(newPage < 1 || newPage > adf.sb.pageCount || newPage > adf.sb.maxPages)
    {
        // Just ignore the request
        return;
    }
    
    updateAnimations();
}

function updatePagingIndicator()
{
    setTimeout("updatePaging()", 100);
}

function updatePaging()
{
    // Build out the pages
    var newHTML = '';
    if(adf.sb.pageCount > 1)
    {
        for(var i = 0; i < adf.sb.pageCount; i++)
        {
            if(i == adf.sb.currentPage-1)
            {
                newHTML += adf.sb.pageOn;
            }
            else
            {
                newHTML += adf.sb.pageOff;
            }
        }
    }
    // Update the content
    $("#paging").html(newHTML);
}

function incrementPage()
{
    if(adf.sb.pageCount < 2)
    {
        return;
    }
    adf.sb.previousPage = adf.sb.currentPage;
    adf.sb.currentPage++;
    if(adf.sb.currentPage > adf.sb.pageCount)
    {
        adf.sb.currentPage = adf.sb.pageCount;
        // Fake left - moves left and then bounces back
        var cssRuleCode = document.all ? 'rules' : 'cssRules'; //account for IE and FF
        var rule = document.styleSheets[adf.sb.activeLayoutCssIndex][cssRuleCode][adf.sb.currentPage-1];
        if(adf.sb.alternateFakeLeft)
        {
            rule.style.setProperty('-webkit-animation',"fakeLeft 0.95s 1", null);
            adf.sb.alternateFakeLeft = !adf.sb.alternateFakeLeft;
        }
        else
        {
            rule.style.setProperty('-webkit-animation',"fakeLeft 1.05s 1", null);
            adf.sb.alternateFakeLeft = !adf.sb.alternateFakeLeft;
        }
        // Reset the paging swipe detection
        touchCancel(null, "Fake Page Change");
        return;
    }
    adf.sb.hideAnimation = "hideToLeft";
    adf.sb.showAnimation = "showFromRight";
    showPage(adf.sb.currentPage);
}
function decrementPage()
{
    if(adf.sb.pageCount < 2)
    {
        return;
    }
    adf.sb.previousPage = adf.sb.currentPage;
    adf.sb.currentPage--;
    if(adf.sb.currentPage < 1)
    {
        adf.sb.currentPage = 1;
        // Fake right - moves right and then bounces back
        var cssRuleCode = document.all ? 'rules' : 'cssRules'; //account for IE and FF
        var rule = document.styleSheets[adf.sb.activeLayoutCssIndex][cssRuleCode][adf.sb.currentPage-1];
        if(adf.sb.alternateFakeRight)
        {
            rule.style.setProperty('-webkit-animation',"fakeRight 0.95s 1", null);
            adf.sb.alternateFakeRight = !adf.sb.alternateFakeRight;
        }
        else
        {
            rule.style.setProperty('-webkit-animation',"fakeRight 1.05s 1", null);
            adf.sb.alternateFakeRight = !adf.sb.alternateFakeRight;
        }
        // Reset the paging swipe detection
        touchCancel(null, "Fake Page Change");
        return;
    }  
    adf.sb.hideAnimation = "hideToRight";
    adf.sb.showAnimation = "showFromLeft";
    showPage(adf.sb.currentPage);
}
           
function showPageDiv(pageDivRule)
{
    pageDivRule.style.setProperty('left', adf.sb.pageShowLeft, null);
    pageDivRule.style.setProperty('opacity',adf.sb.showOpacity, null);
    pageDivRule.style.setProperty('-webkit-animation', adf.sb.showAnimation + " 1s 1", null);    
}
function hidePageDiv(pageDivRule)
{
    pageDivRule.style.setProperty('left', adf.sb.pageHideLeft, null);
    pageDivRule.style.setProperty('opacity',adf.sb.hideOpacity, null);
    pageDivRule.style.setProperty('-webkit-animation', adf.sb.hideAnimation + " 1s 1", null);    
}
/**
 * Handles the rotation of the "loading" graphic
 */
function updateAnimations()
{
    // Use webkit animations to move the pages in or out of view
    try
    {
        // Hide the current page
        var cssRuleCode = document.all ? 'rules' : 'cssRules'; //account for IE and FF
        // Swap in the curent pages
        hidePageDiv(document.styleSheets[adf.sb.activeLayoutCssIndex][cssRuleCode][adf.sb.previousPage-1]);
        showPageDiv(document.styleSheets[adf.sb.activeLayoutCssIndex][cssRuleCode][adf.sb.currentPage-1]);
        // Make sure the page indicator shows the new selected page
        updatePagingIndicator();
        // Reset the paging swipe detection
        touchCancel(null, "Animating Page Change");
    }
    catch(e)
    {
        alert("In updateAnimations() ERROR:"+e);
    }
}

function beginLoadingIcons(features)
{
    // Record the features for loading images
    featureList = features;
    try
    {
        //setTimeout("rotateLoader();",50);
        iconLoadIndex = 0;
        continueLoadingIcons();
    }
    catch(e)
    {
        alert("In beginLoadingIcons() ERROR:"+e);
    }
}
 
function getNextSpringboardVisibleFeature()
{
    var f = null;
    while (featureList != null && f == null && featureList.length > iconLoadIndex)
    {
        f = featureList[iconLoadIndex++];
        if(!f.showOnSpringboard)
        {
            f = null;
        }
    }
    return f;
}
  
function continueLoadingIcons()
{        
    var f = getNextSpringboardVisibleFeature();
    if(f != null)
    {
        //alert("next continueLoadingIcons");
        currentLoadIconFeatureId = f.id;
        adfmf.Features.getFeatureImage(currentLoadIconFeatureId, featureImage);
    }
    // After the last image then load the title information
    else
    {
        _fadeInPageOne();
        adfmf.getApplicationInfo(applicationInformation);
    }
}
function _fadeInPageOne()
{
    adf.sb.isLoaded = true;
    var cssRuleCode = document.all ? 'rules' : 'cssRules'; //account for IE and FF
    var pageDivRule = document.styleSheets[adf.sb.activeLayoutCssIndex][cssRuleCode][adf.sb.currentPage-1];
    pageDivRule.style.setProperty('opacity',adf.sb.showOpacity, null);
    pageDivRule.style.setProperty('-webkit-animation', "appearAnimation 0.7s 1", null);    
    pageDivRule.style.setProperty('-webkit-animation-timing-function', "ease", null);    
    setInterval("_restorePagePropertiesAfterChangingCSS();", 100);    
}
function applicationInformation(appInfo)
{
    //alert("in applicationInformation");
    // Make sure the page count is correct
    updatePagingIndicator();
    // Make sure the layout is correct
    verifyLayoutOrentation();
    // Update the title of the page
    adf.sb.appName = appInfo.name;
    // Start the hints going
    resetHints();
    // Set the title
    var t = adf.sb.appName;
    if(typeof RUN_IN_BROWSER_TEST != 'undefined' && RUN_IN_BROWSER_TEST)
    {
        t = t + " (SIMULATED)"
    }
    $("#message").html(t);
    // We have completed loading so notify the framework so it can do anything 
    // it needs to to continue load of the app.  Right now there are no paramters
    // for this call.
    adfmf.springboardLoaded();
}
function featureImage(imageData, featureId)
{
    try
    {
        //alert('in featureImage');
        var theImage = document.getElementById(featureId);
        if(imageData != null)
        {
            theImage.src = "data:image/png;base64," + imageData;
        }
        else
        {
            theImage.src = "css/images/adf.nativeframework.springboard.image.png"
        }
        theImage.parentNode.id = "icon";
        continueLoadingIcons();
    }
    catch(e)
    {
        alert("In featureImage() ERROR:"+e);
    }
}
/**
 * Used to handle touch movements
 */
function touchMove(event) 
{
    // Prevent scrolling on this element
    event.preventDefault();
}
/**
 * When ADF Mobile shows us as active it will call this function if we register
 * it with ADF Mobile through the JavaScript API.  If we are being activated and
 * paramters are being passed to use we will bet them in this call.
 */
function onADFMobileActivation(paramter)
{
    // TODO: Do something with the activation data - if non null
}
/**
 * When ADF Mobile has an error registering our activation handler this method is called.
 */
function errorRegisteringActivationHandler(errorCode) 
{
    alert("Error Registering Activation Handler (" + errorCode + ")");
}
function getNextSpringboardVisibleIndex(currentIndex, features)
{
    for(var i = currentIndex+1; i < features.length; i++)
    {
        if(features[i].showOnSpringboard)
        {
            return i;
        }
    }
    // Return past the feature length
    return NO_NEXT_SPRINGBOARD_VISIBLE_FEATURE;
}
/**
 * When ADF Mobile has finished creating the feature list this method is called.
 */
function renderAllFeatures(features) 
{
    try
    {
        var maxRowsPerPage = 3;
        var maxItemPerRow = 3;
        var i = -1;
        var newhtml = '';
        // Add the backgroud image?
        adf.sb.pageCount = 0;
        var totalFeatureCount = 0;
        for(var pageNumber = 1; pageNumber <= adf.sb.maxPages && i < features.length; pageNumber++)
        {
            newhtml += '<div id="page0' + pageNumber + '">';
            for(var rowNumber = 1; rowNumber <= maxRowsPerPage && i < features.length; rowNumber++)
            {
                newhtml += '<div id="row0'+rowNumber+'">';
                for(var itemNumber = 1; itemNumber <= maxItemPerRow && i < features.length; itemNumber++)
                {
                    // TODO: Get the next feature that should be on the 
                    // springboard
                    i = getNextSpringboardVisibleIndex(i, features);
                    if(i != NO_NEXT_SPRINGBOARD_VISIBLE_FEATURE)
                    {
                        var f = features[i];
                        if(f != null)
                        {
                            totalFeatureCount++;
                            newhtml += '<div id="item0'+itemNumber+'" onclick="javascript:onSelectFeature(\''+f.id+'\');">';
                            
                            // Item Content
                            newhtml += '<div id="icon">';
                            newhtml += '<img id="'+f.id+'" src="" alt="">';
                            newhtml += '</img>';
                            newhtml += '</div>';
                            
                            newhtml += '<div id="title">';
                            newhtml += '<a rel="external" href="javascript:;">';
                            newhtml += f.name;
                            newhtml += '</a>';
                            newhtml += '</div>';
                            
                            newhtml += '</div>';
                        }
                    }
                }    
                newhtml += '</div>';
            }
            newhtml += '</div>';
        }
        adf.sb.pageCount = Math.ceil(totalFeatureCount/9);
        // Begin loading the icons
        beginLoadingIcons(features);
        // Update the content
        //alert(newhtml);
        $("#springboard").html(newhtml);
    }
    catch(e)
    {
        alert("In renderAllFeatures() ERROR:"+e);
    }
}

/**
 * When ADF Mobile has an error getting features this method is called.
 */
function noFeatures(errorCode) 
{
    var html = '';
    html += 'No Features ('+errorCode+')';
    displayMessage(html);    
}

/**
 * When ADF Mobile has an error showing a feature this method is called.
 */
function errorShowingFeature(errorCode) 
{
    alert("Error Showing Feature (" + errorCode + ")");
}
/**
 * When a user selects a feature this method is called.
 */
function onSelectFeature(featureId)
{
    displayDebugMessage("Show Feature: "+featureId);
    showFeatureComplex(featureId)
}

/**
 * A sample of how to select a feature in a simple manner with no
 * paramters being passed.
 */
function showFeatureSimple(featureId)
{
    try
    {
        adfmf.Features.showFeature(featureId, errorShowingFeature);
    }
    catch(e)
    {
        alert("In showFeatureSimple() ERROR:"+e);
    }
}

/**
 * A sample of how to select a feature in a complex manner with a
 * complex paramter being passed.
 */
function showFeatureComplex(featureId)
{
    try
    {        
        // Show the feature
        adfmf.Features.showFeatureWithParameters(featureId, {}, errorShowingFeature);    
    }
    catch(e)
    {
        alert("In showFeatureComplex() ERROR:"+e);
    }
}


/**
 * Document is done loading this is called and we add a listener for the 
 * phonegap event 'deviceready'.
 */
function onBodyLoad()
{
    if(typeof _SIMULATE_phonegap != 'undefined' && _SIMULATE_phonegap())
    {
        // Do nothing...the above call will 
        // kick off the simulation
    }
    else
    {
        document.addEventListener("deviceready",onDeviceReady,false);
    }
}
/**
 * When this function is called, PhoneGap has been initialized and is ready to roll.
 */
function onDeviceReady()
{
    try
    {
        if(typeof _SIMULATE_adfmf != 'undefined')
        {
            _SIMULATE_adfmf();            
        }
        // Fire a function that checks the orientation every x milliseconds
        setInterval(checkOrientation, adf.sb.orientationCheckInterval);
        setInterval(cycleMessages, adf.sb.messageSpeed);
        setInterval(resetHints, adf.sb.hintsAgainDelay);
        // Register our activation handler
        adfmf.Features.registerActivationHandler(onADFMobileActivation, errorRegisteringActivationHandler);
        // Load the skin for this application
        adfmf.getAmxIncludeList(loadIncludes);
    }
    catch(e)
    {
        alert("In onDeviceReady() ERROR:"+e);
    }
}
var $head;
function loadIncludes(includes)
{
    $head = $head || $("head");
    // Load all the includes - skins - should all have "file://" prefix
    for(var i = 0; i < includes.length; i++)
    {
        var cssLink = document.createElement('link');
        cssLink.setAttribute('rel', "stylesheet");
        cssLink.setAttribute('href', includes[i].file);
        $head.append(cssLink);
    }
    // Have adfmf.Features get us the feature list
    adfmf.Features.listAvailable(renderAllFeatures, noFeatures);    
}
// Swipe detection code.
function touchStart(event) 
{
    // Disable the standard ability - we do not support anything
    // but a single touch ability
    //event.preventDefault();
    if(!isTouchInitialized())
    {
        return;
    }
    
    // Look for one finger touch
    if ( event.touches.length == 1 )
    {
        //event.preventDefault();
        // Get the location of the starting touch
        adf.sb.startTouch.x = event.touches[0].pageX;
        adf.sb.startTouch.y = event.touches[0].pageY;
        adf.sb.startTouch.active = true;
    } 
    else 
    {
        // Cancel out if we only have on finger
        touchCancel(event, "touchStart:multitouch");
    }
}

function touchMove(event) 
{
    // Again only our code should be doing anything
    if(!isTouchInitialized("touchMove"))
    {
        return;
    }
    // If this is a single touch then record the
    // moved touch as a the end touch
    if ( event.touches.length == 1 ) 
    {
        event.preventDefault();
        adf.sb.endTouch.x = event.touches[0].pageX;
        adf.sb.endTouch.y = event.touches[0].pageY;
        adf.sb.endTouch.active = true;
    } 
    else 
    {
        event.preventDefault();
        touchCancel(event, "touchMove:multitouch");
    }
}
function resetHints()
{
    adf.sb.activeHints = adf.sb.hints.slice();
}
function cycleMessages()
{
    if(adf.sb.messageQueue.length > 0)
    {
        var newMessage = adf.sb.messageQueue.shift();
        if(adf.sb.messageQueue.length > 3)
        {
            newMessage += "..." + adf.sb.messageQueue.length;
        }
        if(newMessage != null)
        {
            $("#message").html(newMessage);  
        }
    }
    else if(adf.sb.activeHints.length > 0)
    {
        var newHint = adf.sb.activeHints.shift();
        if(newHint != null)
        {
            $("#message").html(newHint);  
        }
    }    
    else
    {
        var t = adf.sb.appName;
        if(typeof RUN_IN_BROWSER_TEST != 'undefined' && RUN_IN_BROWSER_TEST)
        {
            t = t + " (SIMULATED)";
        }
        $("#message").html(t);  
    }
}
function displayDebugMessage(newMessage)
{
    if(adf.sb.debug)
    {
        adf.sb.messageQueue.push(newMessage);
    }
}
function displayMessage(newMessage)
{
    adf.sb.messageQueue.push(newMessage);
}
function touchCancel(event, reason)
{
    adf.sb.endTouch.active = false;
    adf.sb.startTouch.active = false; 
    displayDebugMessage(reason);
}
function isTouchInitialized(functionName)
{
    if(adf.sb.startTouch == null)
    {
        alert("adf.sb.startTouch not initialized in "+functionName);
        return false;
    }
    if(adf.sb.endTouch == null)
    {
        alert("adf.sb.endTouch not initialized in "+functionName);
        return false;
    }
    return true;
}
function touchEnd(event) 
{
    try
    {
        if(!isTouchInitialized("touchEnd"))
        {
            return;
        }
        // check to see if more than one finger was used and that there is a and ending coordinate
        if ( adf.sb.startTouch.active &&  adf.sb.endTouch.active ) 
        {
            event.preventDefault();
            // use the Distance Formula to determine the length of the swipe
            swipeLength = Math.round(Math.sqrt(Math.pow(adf.sb.endTouch.x - adf.sb.startTouch.x,2) + Math.pow(adf.sb.endTouch.y - adf.sb.startTouch.y,2)));
            horzDiff = Math.abs(adf.sb.startTouch.x - adf.sb.endTouch.x);
            vertDiff = Math.abs(adf.sb.startTouch.y - adf.sb.endTouch.y);
            if ( swipeLength >= adf.sb.minimumSwipeLength ) 
            {
                var direction = determineSwipeDirection();
                if(direction == "left" )//|| direction == "down")
                {
                    incrementPage();
                }
                else if(direction == "right" )//|| direction == "up")
                {
                    decrementPage();
                }
            } 
            else 
            {
                touchCancel(event,"touchEnd:swipelength:" + swipeLength);
            }	
        } 
        else 
        {
            touchCancel(event,"touchEnd:noactive:" + adf.sb.startTouch.active + ":" + adf.sb.endTouch.active);
        }

    }
    catch(e)
    {
        alert("In touchEnd() ERROR:"+e);
    }
}

function caluculateAngle() 
{
    var X = adf.sb.startTouch.x - adf.sb.endTouch.x;
    var Y = adf.sb.startTouch.y - adf.sb.endTouch.y;
    var Z = Math.round(Math.sqrt(Math.pow(X,2)+Math.pow(Y,2))); //the distance - rounded - in pixels
    var r = Math.atan2(Y,X); //angle in radians (Cartesian system)
    var swipeAngle = Math.round(r*180/Math.PI); //angle in degrees
    if ( swipeAngle < 0 ) 
    { 
        swipeAngle =  360 - Math.abs(swipeAngle); 
    }
    return swipeAngle;
}

function determineSwipeDirection() 
{
    var swipeDirection;
    var swipeAngle = caluculateAngle();
    if ( (swipeAngle <= 45) && (swipeAngle >= 0) ) 
    {
        swipeDirection = 'left';
    } 
    else if ( (swipeAngle <= 360) && (swipeAngle >= 315) ) 
    {
        swipeDirection = 'left';
    } 
    else if ( (swipeAngle >= 135) && (swipeAngle <= 225) ) 
    {
        swipeDirection = 'right';
    } 
    else if ( (swipeAngle > 45) && (swipeAngle < 135) ) 
    {
        swipeDirection = 'down';
    } 
    else 
    {
        swipeDirection = 'up';
    }
    return swipeDirection;
}
           
// Check orientation
function checkOrientation() 
{
    try
    {
        var deviceWidth = $('body').width();
        //alert("in checkOrientation: " + deviceWidth);
        var newOrientation = 0;
        if (deviceWidth < 400) 
        {
            newOrientation = 0;
        }
        else //if (deviceWidth == '480') 
        {
            newOrientation = 1;
        }
        
        // If orientation changed since last check, fire either the portrait or landscape function
        if (newOrientation != adf.sb.orientation) 
        {
            adf.sb.orientation = newOrientation;
            verifyLayoutOrentation();
        }
    }
    catch(e)
    {
        alert("In checkOrientation() ERROR:"+e);
    }
}

function verifyLayoutOrentation()
{
    switch (adf.sb.orientation)
    {
        case 0:
            changedToPortrait();
            break;
        case 1:
            changedToLandscape();
            break;
    }    
}

// Landscape stuff
function changedToLandscape() 
{
    try
    {
        if(document.getElementById('layout').href.match(/landscape.css$/))
        {
            return;
        }
        // Change Layout
        document.getElementById('layout').href = 'css/adf.springboard.iphone.landscape.css'
        adf.sb.pageHideLeft = "480px";    
        if(adf.sb.isLoaded)
        {
            restorePagePropertiesAfterChangingCSS();
        }
    }
    catch(e)
    {
        alert("In changedToLandscape() ERROR:"+e);
    }
}

// Portrait stuff
function changedToPortrait() 
{
    try
    {
        if(document.getElementById('layout').href.match(/portrait.css$/))
        {
            return;
        }
        // Change Layout
        document.getElementById('layout').href = 'css/adf.springboard.iphone.portrait.css';
        adf.sb.pageHideLeft = "320px";  
        if(adf.sb.isLoaded)
        {
            restorePagePropertiesAfterChangingCSS();
        }
    }
    catch(e)
    {
        alert("In changedToPortrait() ERROR:"+e);
    }
}         
function restorePagePropertiesAfterChangingCSS()
{
    setTimeout("_restorePagePropertiesAfterChangingCSS();", 30);
}
function _restorePagePropertiesAfterChangingCSS()
{
    try
    {
        // Build out the pages
        var cssRuleCode = document.all ? 'rules' : 'cssRules'; //account for IE and FF
        if(typeof cssRuleCode == 'undefined')
        {
            return;
        }
        var styleSheet = document.styleSheets[adf.sb.activeLayoutCssIndex];
        if(typeof styleSheet == 'undefined')
        {
            return;
        }
        var ruleCodeArray = styleSheet[cssRuleCode];
        for(var i = 0; i < adf.sb.pageCount; i++)
        {
            var rule = ruleCodeArray[i];
            if(i == adf.sb.currentPage-1)
            {
                rule.style.setProperty('left', adf.sb.pageShowLeft, null);
                rule.style.setProperty('opacity', adf.sb.showOpacity, null);
            }
            else
            {
                rule.style.setProperty('left', adf.sb.pageHideLeft, null);
                rule.style.setProperty('opacity', adf.sb.hideOpacity, null);
            }
        }
    }
    catch(e)
    {
        alert("In _restorePagePropertiesAfterChangingCSS() ERROR:"+e);
    }
}
