﻿/// <reference path="../API/Agility.js" />
/// <reference path="../External/jquery-ui-1.7.2.custom.min-vsdoc.js" />

/*  
    NAMESPACE:   DailyFullSchedule
    DESCRIPTION: Defines functionality of the DailyFullSchedule control
    USAGE:       Call DailyFullSchedule.OnInit({object} constants) on document.ready to get everything ready/bound.
                 Call DailyFullSchedule.Load({Date} date) to load/display show data.
*/

if (typeof(DailyFullSchedule) == 'undefined') 
{
    window.DailyFullSchedule = {};
}

(function(DailyFullSchedule, $) {

    //
    // Object: Constants for this module. Are passed in via the OnInit function.
    DailyFullSchedule.Constants = {
        DaySelectorContainerID: "",
        CurrentDailyViewID: "",
        OtherDailyViewID: "",
        TimeZoneDropdownID: "",
        DailyScheduleContainerID: "",
        DailyScheduleByShowContainerID: "",
        // Classes
        DailyShowListingClass: "",
        DailyShowListingByNameClass: "",
        DateOptionClass: "",
        DateOptionSelectedClass: "",
        AirTimeClass: "",
        // URLs
        WebServiceBaseUrl: "",
        ShowListingTemplateUrl: "",
        DateOptionsTemplateUrl: "",
        ShowListingByNameTemplateUrl: ""
    };

    //
    // Object: manage state
    DailyFullSchedule.State = {
        Initialized: false,
        DateOptionsLoaded: false,
        DisplayMode: "AirTime", // AirTime or ShowName
        LastShowDataResult: null
    }

    //
    // Function: Call on $(document).ready()
    DailyFullSchedule.OnInit = function(constantsObj) {
        var consts = DailyFullSchedule.Constants;

        // Initialize constants
        consts = $.extend(consts, constantsObj);
        DailyFullSchedule.State.Initialized = true;

        // Initialize event bindings
        $("#" + consts.TimeZoneDropdownID).change(function() {
            _updateShowTimesByOffset($(this).val());
        });
        $("#" + consts.OtherDailyViewID).click(function() {
            _changeActiveView();
        });
    }

    DailyFullSchedule.LoadResults = function(results) {
        //alert("in");
        DailyFullSchedule.State.LastShowDataResult = result;
        DailyFullSchedule._loadResults(result);
    }

    //
    // Function: Call to load the schedule for the specified date.
    DailyFullSchedule.Load = function(date) {

        if (DailyFullSchedule.State.Initialized) {
            if (!DailyFullSchedule.State.DateOptionsLoaded) {
                _loadDateOptions();
            }
            if (!date) date = new Date();
            _loadShowData(date);
        }
        else {
            if (typeof (console) != "undefined") {
                alert("DailyFullSchedule: Must call OnInit before calling Load.");
            }
        }
    }

    //
    // Function: Gets the short string representation of the weekday for the given date.
    DailyFullSchedule.GetDaySelectorDay = function(date) {
        var days = ["SUN", "MON", "TUES", "WED", "THU", "FRI", "SAT"];
        return days[date.getDay()];
    }

    // private function: load date selector
    function _loadDateOptions() {
        var consts = DailyFullSchedule.Constants,
        $daySelector = $("#" + consts.DaySelectorContainerID),
        selectedClass = consts.DateOptionSelectedClass,
        dateList = new Array();

        for (var i = 0; i < 7; i++) {
            var date = new Date();
            date.setDate(date.getDate() + i);
            dateList[i] = date;
        }
        $daySelector.setTemplateURL(consts.DateOptionsTemplateUrl);
        $daySelector.processTemplate(dateList);
        $("." + consts.DateOptionClass + ":first").addClass(selectedClass);

        $("." + consts.DateOptionClass).click(function() {
            var date = new Date(),
            dateStr = $(this).attr("date");

            date.setTime(Date.parse(dateStr));
            $("." + consts.DateOptionClass).removeClass(selectedClass);
            $(this).addClass(selectedClass);
            DailyFullSchedule.Load(date);
        });

        DailyFullSchedule.State.DateOptionsLoaded = true;
    }

    // private function: load data for all shows on a given date
    function _loadShowData(date) {

        var startDateStr = dateFormat(date, "ddmmyyyy"),
        servicePath = "TVDailySchedule/" + startDateStr;

        _callService(servicePath, function(result) {
            DailyFullSchedule.State.LastShowDataResult = result;
            _loadResults(result);
        });
    }

    DailyFullSchedule.callService_Callback = function(result) {

        DailyFullSchedule.State.LastShowDataResult = result;
        _loadResults(result);
    }

    // private function: call TVSchedule web service
    function _callService(servicePath, fnCallback) {

        servicePath = DailyFullSchedule.Constants.WebServiceBaseUrl + servicePath + "?method=DailyFullSchedule.callService_Callback";
        $.ajax({
            //ifModified: true,
            url: servicePath,
            contentType: "application/json; charset=utf-8",
            dataType: "jsonp"
        });
    };

    function _loadResults(result) {

        // Variables (conditional on whether the display mode is AirTime or ShowName)
        var byAirTime = DailyFullSchedule.State.DisplayMode == "AirTime",
        consts = DailyFullSchedule.Constants,
        containerID = byAirTime ? consts.DailyScheduleContainerID : consts.DailyScheduleByShowContainerID,
        templateUrl = byAirTime ? consts.ShowListingTemplateUrl : consts.ShowListingByNameTemplateUrl;

        result = byAirTime ? result : _organizeDataByShowName(result);

        // Process template and load results    
        var $container = $("#" + containerID);
        if (!$container.hasTemplate()) {
            $container.setTemplateURL(templateUrl, null, { filter_data: false });
        }
        $container.processTemplate(result);
        _updateShowTimesByOffset($("#" + consts.TimeZoneDropdownID).val());

        //Bind Accreditations Cap
        $("#DailyScheduleContainer").find("span.ShowName[accreditations]").each(function() {
            var show = $(this);
            var cap = $("<img class='Cap' alt='' src='" + Agility.ResolveUrl("~/Images/Cap.png") + "'/>");
            show.append(cap);
            _bindCapToolTip(cap);
        });
    };

    function _bindCapToolTip(cap) {
        cap.tooltip({
            delay: 0, showURL: false, track: true, //top: -200, left: -30, //positionLeft: true,
            bodyHandler: function() {
                var capIcon = $(this);
                var popup = $("<div/>");
                popup.addClass("AccreditationsPopup");
                if (capIcon.data("AccreditationsList") == undefined) {
                    popup.html("<div><img src='" + Agility.ResolveUrl("~/Images/loading.gif") + "' alt='' /></div>");
                    var acc = capIcon.parent().attr("accreditations");
                    popup.find("div:first").load(Agility.ResolveUrl("~/HTTPHandlers/Accreditations.ashx?accreditationIDs=" + acc),
                    function(responseText, textStatus, XMLHttpRequest) {
                        capIcon.data("AccreditationsList", responseText);
                    });
                }
                else {
                    popup.html("<div>" + capIcon.data("AccreditationsList") + "</div>");
                }
                return popup;
            }
        });
    };

    //private function: changes the displayed shows based on the given offset
    function _updateShowTimesByOffset(offsetString) {
        var consts = DailyFullSchedule.Constants,
        zoneOffset = parseFloat(offsetString);
        if (!isNaN(zoneOffset)) {
            var minOffset = -1 * zoneOffset,
            maxOffset = minOffset + 23.5;

            $("." + consts.DailyShowListingClass).each(function() {
                //Hide or show based on the offset
                var offset = $(this).attr("offset");
                if (offset < minOffset || offset > maxOffset) {
                    $(this).hide();
                } else {
                    $(this).show();
                }

                // Update the date text
                var $airTime = $("." + consts.AirTimeClass, $(this)),
                airTimeText = $airTime.attr("basetime");
                airTimeText = ApplyOffsetToTimeText(airTimeText, zoneOffset);
                //console.log($airTime.text() + "->" + airTimeText);
                $airTime.text(airTimeText);
            });

            $("." + consts.DailyShowListingByNameClass + " ." + consts.AirTimeClass).each(function() {
                //Hide or show times based on the offset
                var offset = $(this).attr("offset"),
                airTimeText = $(this).attr("basetime");
                airTimeText = ApplyOffsetToTimeText(airTimeText, zoneOffset);
                $(this).text(airTimeText);
                if (offset < minOffset || offset > maxOffset) {
                    $(this).removeClass("visibleAirtime").hide();
                } else {
                    $(this).addClass("visibleAirtime").show();
                }
            });

            $("." + consts.DailyShowListingByNameClass).each(function(i) {
                if ($(".visibleAirtime", $(this)).length == 0) {
                    $(this).hide();
                } else {
                    $(this).show();
                }
            });
        }
    };

    function _changeActiveView() {
        var state = DailyFullSchedule.State,
        consts = DailyFullSchedule.Constants,
        viewingByAirTime = state.DisplayMode == "AirTime";

        if (viewingByAirTime) {
            state.DisplayMode = "ShowName";
            $("#" + consts.CurrentDailyViewID).text("Show Name");
            $("#" + consts.OtherDailyViewID).text("Air Time");
            $("#" + consts.DailyScheduleByShowContainerID).show();
            $("#" + consts.DailyScheduleContainerID).hide();
        }
        else {
            state.DisplayMode = "AirTime";
            $("#" + consts.CurrentDailyViewID).text("Air Time");
            $("#" + consts.OtherDailyViewID).text("Show Name");
            $("#" + consts.DailyScheduleContainerID).show();
            $("#" + consts.DailyScheduleByShowContainerID).hide();
        }

        _loadResults(state.LastShowDataResult);
    };

    function _organizeDataByShowName(result) {
        // Sort results alphabetically
        var resultCopy = result.GetDailyScheduleResult.slice(0);
        resultCopy.sort(function(a, b) {
            a = a.ShowName;
            b = b.ShowName;
            for (var i = 0; i < Math.min(a.length, b.length); i++) {
                if (a[i] > b[i]) return 1;
                else if (a[i] < b[i]) return -1;
            }
            return b.length - a.length;
        });

        // Re-jig the data structure to group by name
        var newResults = {};
        for (var i = 0; i < resultCopy.length; i++) {
            var show = resultCopy[i];
            if (newResults[show.ShowName]) {
                // This show is already in the results -> Just add the time/offset
                var numDates = newResults[show.ShowName].ShowTimes.length;
                newResults[show.ShowName].ShowTimes[numDates] = {
                    Time: show.ShowTime,
                    Offset: show.StartTimeOffset
                };
            }
            else {
                // This show is not in the results yet -> Add all its details
                newResults[show.ShowName] = {
                    ShowName: show.ShowName,
                    ShowTimes: [{ Time: show.ShowTime, Offset: show.StartTimeOffset}],
                    ShowURL: show.ShowURL
                }
            }
        }

        return newResults;
    };

})(DailyFullSchedule, jQuery);

   
    