/*
** FrameChannel Client,  This client determines its personality based on position in the web tree
**                       and can be used for PhilipsTV, WII-B, etc. To create new personalities add 
**                       a subdirectory with the personality name you want to assume in the path, 
**                       and add a symbolic link to this file
** hitory:
**    06/10/2009   lec - Wrote original for echostar
**    07/12/2009   lec - Generalized and expanded for Philips TV
**    07/21/2009   lec - expanded to support crossfade and caching.
**    09/10/2009   lec - removed fraction in position and padding 
**    09/10/2009   lec - Made changes to generalize player
** 
*/ 

var profile = new Object;       // build a little container 
var using_server = "rss.framechannel.com"; // overriden by location.host placeholder

var show_progress = true;       // Used to show progress bar once 
var doTicker = false;
var doDebug = false;            // set to true to dump to console
ONSCREEN  = "0px";
OFFSCREEN = "-1300px";
/*
** Use this to debug with local server
*/

var filter = /^([1-9][0-9]{0,2})+\.([1-9][0-9]{0,2})+\.([1-9][0-9]{0,2})+\.([1-9][0-9]{0,2})+$/;

function main_parse_id_xml(xml_dom, callback_val ) 
{
    /*
    ** This is a call back function from parse xml file obtained from the FrameChannel website
    ** or if the callback value is set to anything but null. If callback_val is not null and 
    ** xml_ dom is, the cookie value added again in an effort to push the expiration time by a year.
    */

    if( xml_dom ) 
    {
        var item = xml_dom.getElementsByTagName("frameId");
        /*
        ** This should be much cleaner but we know the structure of the file so just pull
        ** the value - revisit and cleanup
        */
        profile.unique_id = item[0].childNodes[0].nodeValue;
        
        // Cookies last for a year - Should we update to force 1 year from last use?
        profile.set_cookie(profile.cookie_name, profile.unique_id, 365,"/");
    } else {
        if( callback_val != null ) 
        {
            profile.set_cookie(profile.cookie_name, callback_val, 365, "/");
        }
    }
    
}

function main_stb_gotid_ok( arg ) 
{
    /*
    ** The get unique_id_method will pass a record containg and id
    */
    profile.unique_id = arg;
}
function main_stb_gotid_fail( err )
{
    /*
    ** Should we attempt to get the ID from the website on a failure here?
    */
     profile.debug('Error returned from get_unique_id_method');
}
        
function main_get_id() 
{
    var callback_val = 0; 
   
    if( profile.get_unique_id_method ) 
    {
        /*
        ** Because some implementation may have a native method for obtaining a unique id, defer to that
        ** method if it exists, the method will be populated by the init function and since it may be an
        ** asynchronous method pass a success and failure callback functions
        */
        profile.get_unique_id_method(main_stb_gotid_ok, main_stb_gotid_fail);
    } else {
        /* 
        ** No uniqueness method, check the cookie, if extant fetch value if not create value
        */
        var cookie = null;
        cookie = profile.get_cookie(profile.cookie_name);
        if( cookie && cookie != "" ) 
        {
            profile.unique_id = cookie;
            /*
            ** The id is already valid, however we want to refresh the cookie's expiration, use the
            ** call back function from above but pass a 1 on the callback value to indicate we don't want
            ** to parse, just the refreshing of the cookie expiration
            */
            callback_val = cookie; 
            main_parse_id_xml(null, callback_val )
            
        } else {
            profile.load_xml(profile.getID,main_parse_id_xml,callback_val);
        }
        
    }
    
}

/*
 Function to start the framechannel app
 */
function framechannel_client_starter(is_init)
{
    
    profile.unique_id  = "";
    if( is_init )
    {
        main_get_id();
        frame_app_feed_start();
    }
    else
    {
        profile.debug('SDK failed to initialize properly!');
    }
}

//set page event handlers

if (window.attachEvent) { // check if they are viewing this with IE
    window.attachEvent("onload", loadit);
 } else { // everything else
    window.addEventListener('load', loadit, false );
 }

function loadit ()
{
    initialize(framechannel_client_starter);
}

function frame_app_parse_feed(xml_dom, callback_val)
{
    var ttl;
    var item;
    var i = 0;
    var hold_over ;
    
    

    if( xml_dom ) 
    {
        /*
        ** Ok have we ever ran?
        */
        if( profile.last_pix != -1 ) 
        {
            // delete all but last slide represented by last_pix
            if( profile.frame_pix.length > 1 )
            {
                /*
                ** Only if not the pairing slide
                */
                hold_over = profile.frame_pix[profile.last_pix];
            } else {
                /* Paring slide, make believe we have not ran */
                profile.last_pix = -1;
            }
            
            
            
            for( i = 0 ;  i < profile.frame_pix.length; i++ )
            {
                // the reference created above should prevent garbage collector from dumping last_pix
                delete( profile.frame_pix[i]);
            }
            delete( profile.frame_pix );

        } 
        profile.frame_pix = new Array(0);

        item = xml_dom.getElementsByTagName("ttl");
        ttl = item[0].textContent;
        if( ttl == null || ttl < 0 || ttl > 1000 ) {
            ttl = 2;
        }
        ttl = ttl * 60000;
        if( doTicker ) 
        {
            kickoffTicker(profile);
            doTicker = false;
        }
        
        if( profile.browser == "Firefox" || profile.browser == "MSIE" ) 
        {
            var tag = "media:content";
        } else {
            var tag = "content";
        }

        var mediaNodes = xml_dom.getElementsByTagName(tag);
        
        for( var i=0; i < mediaNodes.length; i++ ) 
        {
            var slide = new Object;
            slide.url = mediaNodes[i].getAttribute("url");
            slide.wdt = mediaNodes[i].getAttribute("width");
            slide.hgt = mediaNodes[i].getAttribute("height");
            slide.dur = parseInt(mediaNodes[i].getAttribute("duration")) * 1000;
            if( profile.productId == "PhilipsTV" ) 
            {
                slide.transition = "change_focus";
            } else {
                slide.transition = "crossFade";
            }
            

                
            slide.id = "img"+i;
            
            
            slide.img = new Image();
            
            slide.img.src = slide.url;     // this loads the image

            slide.img.onLoad = imagesloaded(mediaNodes.length);
            if( i == profile.last_pix )
            {
                profile.frame_pix.push(hold_over);
                profile.hold_over = slide; // to replace once finished with the slide
            } else {
                profile.frame_pix.push(slide);
            }
            
        }
        
    }
    
    
    /*
    ** OK set us up to do this again ttl millisecond from now
    */
    profile.ttl_timer_id = setTimeout( frame_app_feed_start, ttl );
    profile.feedRefresh = false;
        
        
}

function imagesloaded(target)
{
    /*
    ** bump progress marker
    */
    
    profile.loaded++;
    if ( show_progress ) 
    {
        
        document.getElementById('core').innerHTML = '<div style="text-align: center;'+
            'position: absolute; vertical-align: middle; font-size: 1.5em; width: 100%;">' +
            'LOADING'+
            '<span id="progress_bar"></span></div>';
        document.getElementById('progress_bar').innerHTML = '<hr width="'
            + ((profile.width/target)*profile.loaded )+'" size="12" noshade="noshade" />'; 
    }
    
    /*
    ** kick the image loaded timer once we are fully loaded
    */
    if( profile.loaded >= target ) 
    {
        /*
        ** If not already running, (i.e. image not up )
        ** schedule us to start
        */
        profile.slide_timer_id = setTimeout( slide_app_display, 500 );
        show_progress = false;

    }
    
}


function slide_app_display()
{
    /* 
    ** Load all images, all but first have opacity set to 0
    */
    var len = profile.frame_pix.length;
    if( len > 0 ) 
    {
        var text = "";
        var duration;
        var index = 0;
        if( profile.frame_pix[index].url.indexOf("mp4") != -1 )
        {
            text +=  "<embed src=\""+ profile.frame_pix[index].url + "\"";
            text += 'autoplay="true" controller="false" pluginspage="http://www.apple.com/quicktime/download/"';
            text += " width=" + parseInt(profile.adjusted_W);
            text += " height="+ parseInt(profile.adjusted_H);
            text += "/embed>";
        } else {
            
            for( var i = 0; i < len; i++ ) 
            {
                
                if( profile.frame_pix[i].transition == "crossFade" ) 
                {
                    var scrpos = ONSCREEN;
                    var opa = 0;
                    
                } else {
                    var scrpos = OFFSCREEN;
                    var opa = 100;
                    
                }
                
                
                
                fitImage(i); // Mainly here to adjust pictures with weird aspec ratios
                text += "<img id= 'img" + i + "' src=\"" + profile.frame_pix[i].url + "\"";
                text += " width=" + parseInt( profile.adjusted_W);
                text += " height="+ parseInt(profile.adjusted_H);
                var style = " style='position:absolute; overflow:hidden; top:0px; left:"+scrpos+"; z-index:5;";
                if ( profile.browser == "MSIE" ) 
                {
                    style += " filter=alpha(opacity="+opa+"); ";
                } else {
                    style += " opacity:"+opa+";";
                }
                    
                if(profile.adjusted_H != profile.height )
                {
                    // OK do we pad the height on this thing?
                    var deltay = (parseInt(profile.height) - parseInt(profile.adjusted_H))/2;
                    style +=  "padding-top: "   + parseInt(deltay) + "px;";
                    style += "padding-bottom: " + parseInt(deltay) + "px;";
                }
                if(profile.adjusted_W != profile.width) 
                {
                    // OK do we pad the width on this thing?

                    var deltax = (parseInt(profile.width)  - parseInt(profile.adjusted_W))/2;
                    style +=  "padding-right: " + parseInt(deltax) + "px;";
                    style +=  "padding-left: "  + parseInt(deltax) + "px;";
                }
                style += "'"; // close style

            
                // we are done 
                text += style + ">";
            }
        }
        set_root_value("core", text );

        //last_pix has the last displayed image of a -1 for initial condition
        profile.opacity = 100;
        
        profile.slide_timer_id = setTimeout(profile.frame_pix[index].transition+
                                            "("+profile.last_pix+","+profile.index+")", TRANSITION_DELTA);
    }
}


function frame_app_feed_start() 
{
    /*
    ** Ok we have all we need to start receiving the feed
    */

    if( profile.unique_id == "" )
    {
        /*
        ** reschedule us for later 
        */
        setTimeout( frame_app_feed_start , 200 );
        return;
    }
    if( profile.slide_timer_id ) 
    {
        /*
        ** Stop any slide timing that is in progress
        */
        clearTimeout(profile.slide_timer_id);
    }
    profile.feedRefresh = true;
    
    var url = profile.xml_feed_stem + profile.unique_id;

    if( using_server == "localhost" || filter.test(using_server) ) 
    {
        // override if debugging useing local server
        url = profile.xml_feed_stem;
    }


    profile.loaded = 0; // keep track of the first load ( for progress bar )
    //show_progress = true;  // make progressbar appear on feed fetches comment out if not wanted
    
    var callback_val = 1;

    
    profile.load_xml(url,frame_app_parse_feed,callback_val);
    
}

function set_root_value (elem, txt_msg) 
{
   if( document.getElementById(elem) )
   {
      document.getElementById(elem).innerHTML = txt_msg;
   }
}

function set_cookie (name, value, expires, path)
{
    var today = new Date();
    today.setTime( today.getTime() );
    var domain = null; //"framechannel.com";
    var junk = null;
    var host = null;
    
    
    if( path == null ) 
    {
        path = "/";
    }
    
    /*
    ** We pass the expiration time in terms of days, convert to milliseconds
    */
    if ( expires )
    {
        expires = expires * 1000 * 60 * 60 * 24;
    }
    var expiration_date = new Date( today.getTime() + (expires) );

    junk = name + "=" + escape(value) +
        ( ( expires ) ? ";expires=" + expiration_date.toGMTString() : "" ) +
        ( ( path    ) ? ";path="    + path :   "" ) +
        ( ( host    ) ? ";host="    + host :   "" ) +
        ( ( domain  ) ? ";domain="  + domain : "" );

    document.cookie = junk;
    
    profile.debug("set the cookie");
    

}

function get_cookie ( check_name )
{
    var a_all_cookies = document.cookie.split( ';' );
    var a_temp_cookie = '';
    var cookie_name = '';
    var cookie_value = '';
    var b_cookie_found = false; // set boolean t/f default f

    for ( i = 0; i < a_all_cookies.length; i++ )
    {
        // now we'll split apart each name=value pair
        a_temp_cookie = a_all_cookies[i].split( '=' );
        

        // and trim left/right whitespace while we're at it
        cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, '');
        
        // if the extracted name matches passed check_name
        if ( cookie_name == check_name )
        {
            b_cookie_found = true;
            // we need to handle case where cookie has no value but exists (no = sign, that is):
            if ( a_temp_cookie.length > 1 )
            {
                cookie_value = a_temp_cookie[1].replace(/^\s+|\s+$/g, '');
            }
            // note that in cases where cookie is initialized but no value, null is returned
            return cookie_value;
            break;
        }
        a_temp_cookie = null;
        cookie_name = '';
    }
    if ( !b_cookie_found )
    {
        return null;
    }
}

var req;

function load_xml ( url, xml_cb, cb_val )
{
    req = false;
    
    if (window.XMLHttpRequest && !(window.ActiveXObject)) 
    {
        try 
        {
            req = new XMLHttpRequest();
        } catch( e ) 
        {
            req = false;
        }
    } else  if(window.ActiveXObject) {
       	try {
            req = new ActiveXObject("Msxml2.XMLHTTP");
      	} catch(e) 
        {
            try 
            {
                req = new ActiveXObject("Microsoft.XMLHTTP");
            } catch(e) 
            {
                req = false;
            }
        }
    }
    if( req )
    {
        if( profile.browser == "Firefox") 
        {
            // uncomment the following only of trying this using "file:///path.to.htmp/url/type"
            //netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead")
            //netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect")
        }
        
        profile.xml_cb = xml_cb;
        profile.cb_val = cb_val;
        req.onreadystatechange = handleStateChange;
        req.open("GET", url, true);
        req.send(null);
   
    }

}

function debug (msg) 
{
    if ( doDebug && ( (profile.browser == "Safari") || ( profile.browser == "Firefox") ) && (msg.length > 0))
    {
        var idx = 0;
        var args = arguments; 
        var pattern = new RegExp("%[s,d,i,f,o]", "g"); 

        console.log(msg.replace(pattern, function(match){ return args[++idx];}));
    }
}


function handleStateChange() 
{
    if (req.readyState == 4 ) 
    {
        if( req.status == 200 )
        {
            
            if( profile.xml_cb )
            {
                var responseXML = req.responseXML;
                eval(profile.xml_cb(responseXML, profile.cb_val ));
                //                responseXML = null;
                //req = null;
            }
        } else {
            alert("Unable to retrieve XML data:\n" + req.statusText);
        }
    }
}

function initialize( cb_funct )
{
    var path = document.location.pathname;
    using_server = location.host;
    
    /*
    ** See about doing this via an xml configuration file, for now brute force for each 
    ** different client
    */

    profile.get_unique_id_method = null;       /* No known unique id method for Philips */
    profile.debug                = debug;      /* set to a stub in console incapable browsers */
    profile.get_cookie           = get_cookie; /* may be overloaded by framework specific method */
    profile.set_cookie           = set_cookie; /* may be overloaded by framework specific method */
    profile.load_xml             = load_xml;   /* may be overloaded by framework specific method */

    profile.productId            = "generic";  /* Set default values, overriden below            */
    profile.width                = "786";     
    profile.height               = "442";
    
    if( path.indexOf("PhilipsTV") != -1 ) 
    {
        /*
        ** Put philips specific stuff
        */
        profile.productId            = "PhilipsTV";
        profile.width                = "1280";     /* string type to eliminate conversion*/
        profile.height               = "720";
        OPACITY_STEP                 = 100;        /* Eliminate cross fade - compensate for bug - */
    }
    else if( (path.indexOf("WII-B") != -1 ) || (path.indexOf("wii") != -1 ) )
    {
        profile.productId            = "WII-B";
        profile.width                = "786";     /* Note these are strings to eliminate a coversion */
        profile.height               = "442";
        
    } 
    else if( path.indexOf("JVC001") != -1 ) 
    {
        profile.productId            = "JVC001";
        profile.width                = "1280";     /* string type to eliminate conversion*/
        profile.height               = "720";
        
    } 
    else if( path.indexOf("archos") != -1 ) 
    {
        profile.productId            = "ARCHOS5";
        profile.width                = "800";     /* string type to eliminate conversion*/
        profile.height               = "438";
        
    } 
    else if( path.indexOf("LG001") != -1 ) 
    {
        profile.productId            = "LG001";
        profile.width                = "1920";     /* string type to eliminate conversion*/
        profile.height               = "1080";
        
    } 
    else if( path.indexOf("TO002") != -1 ) 
    {
        profile.productId            = "TO002";
        profile.width                = "1280";     /* string type to eliminate conversion*/
        profile.height               = "720";

    }    // add elseif clause for additional player characteristics
    /*
    ** Ok, now see if we are overriding the parameters with invocation arguments
    */
    parse_search_string();
    
    profile.adjusted_W           = "786";     /* This will be changed by imagefit function */
    profile.adjusted_H           = "442";      /* This will be changed by imagefit function */
    profile.getID =         "http://"+using_server+"/device/generateId"
    profile.xml_feed_stem = "http://"+using_server+"/productId="+profile.productId+"/frameId=";
    profile.cookie_name = 'framechannel_uniqueID_' + profile.productId;
    profile.last_pix = -1;
    profile.hold_over = null;
    profile.index = 0;
    profile.feedRefresh = false;   /* Flag used to disregard slide timers */
    profile.tickerFeed = "http://ticker.dev.framechannel.com/productId=FMDS001/frameId=robtestid";
 
    if( using_server == "localhost" || filter.test(using_server)) 
    {   // only if debugging using local server note the use of static xml files
         profile.getID =         "http://"+using_server+"/FrameChannelPlayer/fakeID.xml";
         profile.xml_feed_stem = "http://"+using_server+"/FrameChannelPlayer/fakeframe.xml";
         profile.tickerFeed    = "http://"+using_server+"/FrameChannelPlayer/fakefeed.xml";
         
    }
    
    if (navigator.userAgent.indexOf("Opera")!= -1)
    { 
        profile.browser = "Opera"; 
    }
    else if (navigator.userAgent.indexOf("Firefox")!= -1)
    { 
        profile.browser = "Firefox"; 
    }
    else if (navigator.userAgent.indexOf("MSIE")!= -1)
    { 
        profile.browser = "MSIE"; 
    }
    else if (navigator.userAgent.indexOf("Netscape")!= -1)
    { 
        profile.browser = "Netscape"; 
    }
    else if (navigator.userAgent.indexOf("Safari")!= -1)
    { 
        profile.browser = "Safari"; 
    }
    else if (navigator.userAgent.indexOf("Konqueror")!= -1)
    { 
        profile.browser = "Konqueror"; 
    }
    
    cb_funct( true );                        
    
}

function parse_search_string()
{
    var fullurl=window.location.search
    var param=(fullurl.slice(1))

    var pairs = param.split("&")

    for(var i = 0; i < pairs.length; i++)
    {
        var pos = pairs[i].indexOf('=')
        if (pos == -1) continue
        var argname = pairs[i].substring(0,pos)
        var value = pairs[i].substring(pos+1)
        if (argname == "resolution")
        {
            var res = value.split("x");
            profile.width = res[0];
            profile.height = res[1];
        }
        else if ( argname == "productId" ) 
        {
            profile.productId = value;
        }
        else if ( argname == "ticker" )
        {
            if( value == "on" )
            {
                doTicker = true;
            }
        } 
        else if ( argname == "ostep" ) 
        {
            OPACITY_STEP = parseInt(value);
        } 
        else if ( argname == "tbc" ) 
        {
            TICKERBACKGROUND = "#"+value;
        } 
        else if ( argname == "ttc" ) 
        {
            TICKERFOREGROUND = "#"+value;
        } 
        else if ( argname == "ts" ) 
        {
            TICKERSCROLLSPEED = parseInt(value);
        } 
        else if ( argname == "to" ) 
        {
            TICKEROPACITY = parseInt(value)
        }
        
    }

} 
