/**
  * Define the Bio Channel EPG
 **/
HC.epg = {

    /**
     * Private Constants
     */

    SITE_NAME           : "BIO", // bio/military history
    ENVIRONMENT_MODE    : "development",
    CACHE               : false,

    // use keyboard to control epg slider
    useKeyboard         : true,

    // define the channel instances
    CHANNELS            : channels,
    currentChannel      : startChannel,

    // LSHift JSON API vars
    jsonURL             : "http://prototype.hc.lshift.net/prototype-author/sky-import/jsonp-epg.html?",
    mgnlUserId          : "tester",
    mgnlUserPSWD        : "teurivis",
    callBackFunction    : "HC.epg.dataManager.aCallBack",
    duration            : "1440",

    // EPG AJAX (used to get listing and program details from Sky)
    folderPrefix        : this.EPG_DATA_URL + '/',
    fileListing         : this.EPG_DATA_URL + '/tvlistings.json',
    fileProgram         : this.EPG_DATA_URL + '/programmeDetails.json',

    // object to hold cache data
    _epg_data           : {},

    // date time constants
    timeZoneOffset      : "0",
    today               : new Date(),
    isoDate             : $.ISODate("c", new Date()),
    startDay            : -1, // -1 for yesterday; 0 for today; +1 for tomorrow;
    days                : 7,
    // just returns a date in a format required to call Sky JSON data for today
    now                 : $.JSONDate(new Date()),

    months              : new Array("January","February","March","April","May","June","July","August","September","October","November","December"),

    // channel listing vars
    start               : 0,
    currentPane         : 3,
    increment           : 1,

    // currentTimeOfDay pane
    currentPaneDay      : 0,

    iLastEnd            : 0,
    iLastStart          : 0,
    subpanelOffset      : 0,

    // timeOfDay format - split the day into 4 view panes (used for scrolling)
    timeOfDay_format: [{
                            hour: 0,
                            text: "earlymorning",
                            duration: 360,
                            position: '0px'
                        },
                        {
                            hour: 6,
                            text: "morning",
                            duration: 360,
                            position: '924px'
                        },
                        {
                            hour: 12,
                            text: "afternoon",
                            duration: 360,
                            position: '1848px'
                        },
                        {
                            hour: 18,
                            text: "evening",
                            duration: 360,
                            position: '2772px'
                        }],

    programs: [],

    init : function(){

        HC.epg.injectHTML();
        HC.epg.buildChannelNav();
        HC.epg.buildDayNav();

        // bind event clicks for slider and navigation
        HC.epg.bindEventHandlers();

        try
        {
            HC.epg.setProgram(startChannel, startDate, startEventId);
        }
        catch (err)
        {
            HC.epg.setProgram("1873", new Date(), -1);
        }

    },

    setProgram : function(channelId, date, eventId) {
        var channel = channelId;
        HC.epg.currentChannel = channel;
        HC.epg.selectNav.call($('#'+channel));

        HC.epg.currentPaneDay = HC.epg._epg_data[$.JSONDate(date)].position;
        HC.epg.selectNav.call($('.'+HC.epg.getDayClassFromDate(date)));

        HC.epg.getData($.JSONDate(date), channelId);

        if (eventId != -1)
        {
            prog = HC.epg.programs[eventId];
            daySection = HC.epg.getDaySection(prog.startDate);

            HC.epg.currentPane = parseInt(daySection);
            HC.epg.scrollToThis(daySection);
            HC.epg.selectNav.call($('#'+HC.epg.timeOfDay_format[daySection].text));

            prog.selectFunction();
        }
    },

    getDaySection: function(date)
    {
        var hour = date.getHours();

        var i = 1;

        while(i < HC.epg.timeOfDay_format.length)
        {
            if (hour < HC.epg.timeOfDay_format[i].hour)
                return i-1;

            i++;
        }

        //Goto last timespan
        return i-1;
    },

    getDayClassFromDate: function(date)
    {
        return prettyDate($.ISODate("c", date));
    },

    injectHTML : function(){
        $("#epgwrapper").append("<ul id=\"catchItHere\">" +
                "<li class=\"first\">Catch it here:</li>" +
                "<li>Sky 156</li>" +
                "<li>Sky HD 211</li><li>Virgin 242</li>" +
                "</ul>");

        // inject EPG slider and programme details blocks
        $("#epgwrapper").append("<div id=\"slider\"></div>");
        $("#epgwrapper").append("<div id=\"detail\"></div>");

        // inject slider controls
        $("#slider").append("<div class=\"controls\"></div>");
        $("#slider").append("<div class=\"scroll\"></div>");

        // inject navigational elements (channels, days, timeofday)
        $(".controls").append("<ul id=\"channels\"></ul>");
        $(".controls").append("<ul id=\"navigation\"></ul>");
        $(".controls").append("<ul id=\"timeofday\"></ul>");

        // inject scroll container (form daily programme listing)
        $(".scroll").append("<div class=\"scrollContainer\"></div>");

        $("#timeofday").append("<li><a id=\"earlymorning\" href=\"#\"><span class=\"0\">Night</span></a></li>");
        $("#timeofday").append("<li><a id=\"morning\" href=\"#\"><span class=\"1\">Morning</span></a></li>");
        $("#timeofday").append("<li><a id=\"afternoon\" href=\"#\"><span class=\"2\">Afternoon</span></a></li>");
        $("#timeofday").append("<li><a id=\"evening\" href=\"#\"><span class=\"3\">Evening</span></a></li>");

        $(".controls").append("<div id=\"nav\"><a href=\"#\" class=\"prev\"><em></em></a><a href=\"#\" class=\"next\"><em></em></a></div>");

        // inject programme detail block elements
        $("#detail").append("<div id=\"media\"><img src=\"" + images_schedule_detail + "\"></div>");
        $("#detail").append("<div id=\"schedule\"></div>");
        $("#detail").append("<div id=\"actionBtns\"></div>");

        // programme schedule info
        $("#schedule").append("<h3></h3>");
        $("#schedule").append("<h4></h4>");
        $("#schedule").append("<p class=\"desc\"></p>");
        $("#schedule").append("<p class=\"showurl\"><a class=\"redArrowOnWhite\" href=\"\" title=\"\">Visit the shows page</a></p>");
        $("#schedule").append("<p class=\"biourl\"><a class=\"redArrowOnWhite\" href=\"\" title=\"\">Visit the biography page</a></p>");

        // remind me, sky+ record action buttons
        $("#actionBtns").append("<a class=\"btnWide skyRecordNonTransparent-2\" title=\"record this programme with sky\" href=\"#\"><span class=\"fLeft\">Record with</span>&nbsp;<img src=\"http://www.history.co.uk/docroot/images/skyLogoGreyOnWhite.png\" alt=\"sky\" /></a>");
        // $("#actionBtns").append("<a class=\"btnWide remindMeNonTransparent-2\" title=\"remind me\" href=\"#\">Remind me</a>");
        //$("#actionBtns").append("<a class=\"btnWide shareNonTransparent-2\" title=\"share this series\" href=\"#\">Share this series</a>");

    },

    buildChannelNav : function(){
        // create the channels navigation
        jQuery.each(HC.epg.CHANNELS, function(i,val) {
            $('#channels').append("<li><a id=\""+val.id+"\" class=\""+i+"\" href=\""+val.url+"\">"+val.title+"</a></li>");
        });
    },

    buildDayNav : function(){
        for (var i = HC.epg.startDay; i < HC.epg.days; i++){
                var x = new Date();
                x.setDate(HC.epg.today.getDate()+i);

                rel = x.getFullYear() + HC.epg.addLeadingZero(x.getMonth() + 1) + HC.epg.addLeadingZero(x.getDate());
                var y = x;
                var z = $.ISODate("c", y);

                $('#navigation').append("<li><a href=\"#\" class=\""+prettyDate(z)+"\" rel=\""+rel+"0000\"><span class=\""+rel+"0000\">"+prettyDate(z)+"</span></a></li>");
                var f = rel+"0000";

                // generate a dateFrom value for parsing by showsInRange function
                dateFrom = new Date(x.getUTCDate() + ' ' + HC.epg.months[x.getMonth()] + ' ' + x.getFullYear());

                // create and object for managing the days (also used for caching daily data)
                HC.epg._epg_data[f] = {"data" : null, "position" : i, "rel" : rel+"0000", "dateFrom" : dateFrom};
        }
    },

    bindEventHandlers : function(){
        $("#channels li a").click(function(e){
            var channel = e.currentTarget.id;
            HC.epg.currentChannel = channel;
            HC.epg.selectNav.call($('#'+channel));
            HC.epg.getData(HC.epg.now,HC.epg.currentChannel);
            return false;
        });
        $("a.prev").bind("click", function(e){ HC.epg.moveSlider("prev");return false; });
        $("a.next").bind("click", function(e){ HC.epg.moveSlider("next");return false; });
        $("#navigation span").click(function(e){
            HC.epg.currentPaneDay = HC.epg._epg_data[e.currentTarget.className].position;
            HC.epg.selectNav.call($('.'+e.currentTarget.innerHTML));
            HC.epg.getData(e.currentTarget.className,HC.epg.currentChannel);
            return false;
        });
        $("#timeofday span").click(function(e){
            HC.epg.currentPane = parseInt(e.currentTarget.className);
            HC.epg.scrollToThis(e.currentTarget.className);
            HC.epg.selectNav.call($('#'+HC.epg.timeOfDay_format[e.currentTarget.className].text));
            return false;
        });

        if(HC.epg.useKeyboard){
            // bind left,right,up and down keypresses
            $(window).keydown(function (e) {

                if ((e.keyCode == 38 || e.keyCode == 39)) {
                    HC.epg.moveSlider("next");
                    return false;
                }

                if ((e.keyCode == 37 || e.keyCode == 40)) {
                    HC.epg.moveSlider("prev");
                    return false;
                }
            });
        }
    },

    moveSlider : function(e) {

        // setup the scroll object
        var $scroll = $('#slider .scroll').css('overflow', 'hidden');

        // TODO: this is a bit gay - tidy this
        if(e == 'prev'){
            if(HC.epg.currentPane > 0){
                HC.epg.currentPane = HC.epg.currentPane - HC.epg.increment;
                // init the scroll
                $scroll.stop().scrollTo( HC.epg.timeOfDay_format[HC.epg.currentPane].position, 500 );
            } else {
                // load the next bucket
                if(HC.epg.currentPaneDay > HC.epg.startDay){
                    HC.epg.currentPaneDay--;

                    var d = new Date();
                    d.setDate(HC.epg.today.getDate()+HC.epg.currentPaneDay);
                    var jd = d;
                    var gotoDate = $.JSONDate(jd);

                    // highlight the correct day nav
                    var el = $('a[rel="'+gotoDate+'"]');
                    HC.epg.selectNav.call(el);

                    HC.epg.getData(gotoDate,HC.epg.currentChannel);

                    HC.epg.reset();
                }
            }
        }
        if(e == 'next'){
            if(HC.epg.currentPane < 3){
                HC.epg.currentPane = HC.epg.currentPane + HC.epg.increment;
                // init the scroll
                $scroll.stop().scrollTo( HC.epg.timeOfDay_format[HC.epg.currentPane].position, 500 );
            } else {
                // load the previous bucket
                if(HC.epg.currentPaneDay < (HC.epg.days - 1)){
                    HC.epg.currentPaneDay++;

                    var d = new Date();
                    d.setDate(HC.epg.today.getDate()+HC.epg.currentPaneDay);
                    var jd = d;
                    var gotoDate = $.JSONDate(jd);

                    // highlight the correct day nav
                    var el = $('a[rel="'+gotoDate+'"]');
                    HC.epg.selectNav.call(el);

                    HC.epg.getData(gotoDate,HC.epg.currentChannel);

                    HC.epg.reset();
                }
            }
        }

        // select the correct timeofday
        HC.epg.selectNav.call($('#'+HC.epg.timeOfDay_format[HC.epg.currentPane].text));

    },

    scrollToThis : function(value) {
        var $scroll = $('#slider .scroll').css('overflow', 'hidden');
        $scroll.stop().scrollTo( HC.epg.timeOfDay_format[value].position, 500 );
    },

    // handle day nav selection
    selectNav : function () {
        $(this)
            .parents('ul:first')
                .find('a')
                    .removeClass('selected')
                .end()
            .end()
            // select the nav item
            .addClass('selected');
    },

    getData : function(id,channel){

        HC.epg.reset();

        var $subcontainer = $('.scrollContainer');
        $subcontainer.empty();
        $subcontainer.html('fetching data...');

        // reset
        currentPane = 0;

        // LShift implementation need to do something like this
        // get the data (dataType = jsonp)

        // HC.epg.fetchJSONP(id);
        HC.epg.dataManager.get(id,channel);

    },

    // create the channel blocks for each selected day
    addChannels : function (id,data,fromDate){

        var $subcontainer = $('.scrollContainer');
        $subcontainer.fadeOut("fast");

        $subcontainer.empty();

        $subcontainer.append("<ul id=\"programmes\" class=\"panel"+id+"\"></ul>");
        var $daypanel = $('.panel'+id);

        var NOW = new Date();
        NOW = $.JSONDate(fromDate);

        HC.epg.subpanelOffset = 0;

        jQuery.each(data, function(i, val) {

            d = new Date(parseInt(val.start));
            duration = val.dur;
            fdate = $.JSONDate(d);
            fulldate = $.JSONFullDate(d);

            // get program start and end
            // used to highlight currently showin program
            var PROG_DURATION   = (val.dur) * 1000;
            var PROG_START      = val.start;
            var PROG_END        = parseInt(PROG_START) + parseInt(PROG_DURATION);
            var PROG_HOURS      = d.getHours();

            // calculate show starttime
            var showStart = new Date(parseInt(val.start));
            var showTime = new Date(showStart);
            // calculate the show endtime (start + duration)
            var t = showTime.setMinutes(showTime.getMinutes() + parseInt(val.dur));
            // fromDate is passed to the function (it is the current days start time ie 00.00 hours)
            var f = fromDate.getTime();

            //################## INSERTED
            //work out whether there is a thumbnail for the program and if so set an image for its inner HTML
            if (val.thumbnailURL != null)
                progImageHTML = "<img src=\"" + val.thumbnailURL + "\" />";
            else
                progImageHTML = "<div style=\"width : 153px; height : 86px\" />";

            // if the program is scheduled outside of current day 24hour period
            if(!(fdate >= NOW)){

                if(t > f) {
                    // work out the difference and add the extra time to the EPG
                    diff = ((t - f) / 1000);
                    timediff = Math.floor(diff / 60);

                    $daypanel.append("<li id=\"subpanel_"+i+"\" class=\"subpanel prog"+timediff+"\"><a href=\"#\" rel=\""+val.eventId+"\"><span class=\"time\">"+HC.epg.formatTime(d)+"</span><span class=\"progImage\">" + progImageHTML + "<span class=\"\"></span></span><span class=\"title\">"+val.title+"</span></a></li>");
                }

            } else {

                // TODO: deal with 'programme data unvailable'
                diff = ((t - f) / 1000);
                timediff = Math.floor(diff / 60);

                var E = showTime.getTime();
                var S = showStart.getTime();

                if(HC.epg.iLastEnd == 0) {
                    HC.epg.iLastEnd = E;
                }

                if ((S) > (HC.epg.iLastEnd)) {

                    var Q = "Programme information unavailable";
                    var P = (((S - HC.epg.iLastEnd) / 1000) / 60 / 60) * 164;

                    HC.epg.subpanelOffset = P;

                    $daypanel.append("<li id=\"subpanel_"+i+"\" class=\"subpanel offair\" style=\"width:" + P + "px\"><span class=\"text\">"+Q+"</span></li>");

                } else {

                    $daypanel.append("<li id=\"subpanel_"+i+"\" class=\"subpanel prog"+duration+"\"><a href=\"#\" rel=\""+val.eventId+"\"><span class=\"time\">"+HC.epg.formatTime(d)+"</span><span class=\"progImage\">" + progImageHTML + "<span class=\"\"></span></span><span class=\"title\">"+val.title+"</span></a></li>");

                    //if( (NOW > PROG_START) && (NOW < PROG_END) ){
                    if((PROG_HOURS == 18)){
                        activeProgramme = i;
                        $('li > .subpanel').removeClass('selected');
                    }

                    selectProg = function(){
                        HC.epg.updateProgramDetails(val);
                        $('li').removeClass('selected');
                        $('.progImage > span').removeClass('imgBorderActive');
                        $('li#subpanel_'+i).addClass('selected');
                        $('li#subpanel_'+i+' a .progImage span').addClass('imgBorderActive');
                        return false;
                    };

                    HC.epg.programs[val.eventId] = {
                            selectFunction : selectProg,
                            startDate : showStart,
                            data : val
                    };

                    $('#subpanel_'+i+' a').bind('click', selectProg);

                }

                HC.epg.iLastEnd = E;
                HC.epg.iLastStart = S;

            }
        });

        var $subpanels = $('.panel'+id+' > .subpanel');

        // calculate a new width for the bucket container
        $daypanel.css({
            'float' : 'left',
            'position' : 'relative', // IE fix to ensure overflow is hidden
            'width' : ((446 * $subpanels.length) + HC.epg.subpanelOffset)
        });

        $subcontainer.fadeIn("slow");

        // hightlight the current program
        $('li#subpanel_'+activeProgramme+' a').click();
        HC.epg.currentPane = 3;
        HC.epg.scrollToThis(HC.epg.currentPane);

        HC.epg.iLastEnd = 0;
        HC.epg.iLastStart = 0;

    },

    updateProgramDetails: function(obj) {
        var d = new Date(parseInt(obj.start));
        var mediaHTML = "";
        if (obj.detailImageURL != null)
            mediaHTML = '<img src=\"' + obj.detailImageURL + '\">';

        $('#detail #media').html(mediaHTML);
        $('#detail #schedule h3').html(obj.title);
        $('#detail #schedule h4').html(HC.epg.formatDate(d));
        $('#detail #schedule p.desc').html(obj.shortDesc);

        // generate record now link and open in new window
        $('#detail #actionBtns .skyRecordNonTransparent-2').attr({
			'href'		:'http://tv.sky.com/tvlistings?channelId='+obj.channelId+'&eventId='+obj.eventId,
			'target' 	:'_blank'
		});
        
        var pageLink = function (selector, url) {
            if (url == null) {
                $(selector).attr("style", "display : none;");
            } else {
                $(selector).attr("style", "");
                $(selector + ' a').attr("href", url)
            }
        };
        
        pageLink('#detail #schedule p.showurl', obj.showPageURL)
        pageLink('#detail #schedule p.biourl', obj.bioPageURL)

		/* generate sharethis object for this show
		 var object = SHARETHIS.addEntry({
			title: obj.title,
			summary: obj.shortDesc,
			icon: obj.detailImageURL,
			url: obj.showPageURL
			}, {button:false,onclick:HC.epg.shareThisCallback});

		var element = document.getElementById("sharethis_0");
		object.attachButton(element);

    },

	shareThisCallback: function(SharedObject) {
		// need to find a way to stop the page jump
		*/
	},

    // add AM or PM
    formatTime : function(date) {
        var hour = HC.epg.addLeadingZero(date.getHours()),
            min = HC.epg.addLeadingZero(date.getMinutes()) + "";

         //return html encoded hour + ':' + min + ' ' + ampm;
        return "<span class=\"hr\">"+hour+"</span><sup>:"+min+"</sup>";
    },

    // format the date/time for programme details i.e TUESDAY 18:00
    formatDate : function(date) {
        var dayNames = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday");
        return dayNames[date.getDay(date)] + ' ' + HC.epg.addLeadingZero(date.getHours()) + ':' + HC.epg.addLeadingZero(date.getMinutes());
    },

    // add leading zero (for programme listing)
    addLeadingZero : function(iValue) {
        if (iValue < 10) {
            iValue = ("0" + iValue);
        }
        return iValue;
    },

    // reset to default values
    reset : function() {

        // move the slider to default timeofday
        HC.epg.currentPane = 3;

        // select the correct timeofday
        HC.epg.selectNav.call($('#'+HC.epg.timeOfDay_format[HC.epg.currentPane].text));
        // setup the scroll object
        HC.epg.scrollToThis(HC.epg.currentPane);
    }

};

/**
  * CACHE JSON REQUESTS
 **/
HC.epg.dataManager = {

    cache_epg_data  : HC.epg._epg_data,
    cache_epg_item  : null,

    init : function() {
    },

    get : function(id, channelId) {
        // set the item to cache
        this.cache_epg_item = id;

        var c = HC.epg.dataManager.cache_epg_data[id].data;
        var d = HC.epg.dataManager.cache_epg_data[id].dateFrom;

        // if cache is false and there is no cache data for this day perform JSON API query
        if ((HC.epg.CACHE == false) || (c == null)) {

            dateFrom = d;
            dateUntil = new Date(dateFrom);
            dateUntil.setMinutes(dateUntil.getMinutes()+HC.epg.duration);

            var shows = showsInRange(dateFrom, dateUntil, channelId, 1);

            HC.epg.addChannels(HC.epg.currentChannel, shows, d);
            HC.epg.dataManager.cache_epg_data[''+this.cache_epg_item+''].data = shows;

        } else {
            // add the channels using the cached value
            HC.epg.addChannels(HC.epg.currentChannel,c,d);
        }
    }

};

// initialise the EPG on document load
$(document).ready(function(){
    HC.epg.dataManager.epgdata = epgdata;
    HC.epg.init();
    HC.epg.dataManager.init();
});