window.Mediasite = window.Mediasite || {};
Mediasite.Player = Mediasite.Player || {};
Mediasite.Player.PlayCoverHelper = (function () {

    var PROVIDER_TYPE_SERVER = 1;
    var PROVIDER_TYPE_P2G = 2;


    function emptyInfo() {
        return {
            Title: "",
            ThumbnailUrl: null,
            AirDateUnixTimeInMs: 0,
            ServerClockSkew: 0,
            PlayStatus: MediasitePlayCover.PRESENTATION_STATUS.NotAvailable,
            IsLiveCountdownEnabled: false,
            IsLiveIndicationDelayed: false,
            PlayCoverOnlyWhenEmbedded: false,
            AllowedPlayerIFrameAPISites: ["*"]
        };
    };


    function makeServiceCall(serviceMethodPath, presentationId, successCallback, failureCallback) {
        var jsonData = JSON.stringify({ presentationId: presentationId });

        var xhr = new XMLHttpRequest();
        xhr.addEventListener("load", function () {
            var response;

            if (xhr.status < 400) {
                response = xhr.response;
                if (typeof response === "string") {
                    try {
                        response = JSON.parse(response);
                    } catch (err) {
                        response = {};
                    }
                }
                
                successCallback(response && response.d);
            } else {
                failureCallback();
            }
        });
        xhr.open("POST", serviceMethodPath);
        xhr.responseType = "json";
        xhr.setRequestHeader("Content-type", "application/json");
        xhr.send(jsonData);
    }

    
    function ServerStrategy(servicePath) {
        this.contextSupportsPlayCover = true;
        this.getPlayCoverInfo = function (presentationId, successCallback, failureCallback) {
            function success(data) {
                var info = data || emptyInfo();
                info.ServerClockSkew = (new Date()).getTime() - info.ServerTimeForClockSkew;
                successCallback(info);
            }

            makeServiceCall(servicePath + '/' + "GetPlayCoverInfo", presentationId, success, failureCallback);
        };
        this.getPresentationStatus = function (presentationId, successCallback, failureCallback) {
            function success(data) {
                successCallback({
                    status: data && data.PlayStatus
                    // TODO: Maybe add live start time, but will need server clock skew.
                });
                
            }

            makeServiceCall(servicePath + '/' + "GetLiveStatus", presentationId, success, failureCallback);
        };
    }

    function OtherStrategy() {
        this.contextSupportsPlayCover = false;
        this.getPlayCoverInfo = function (presentationId, successCallback, failureCallback) {
            successCallback(emptyInfo());
        };
        this.getPresentationStatus = function (presentationId, successCallback, failureCallback) {
            successCallback({ status: MediasitePlayCover.PRESENTATION_STATUS.NotAvailable });
        };
    }


    function getPlayCoverStrategy(dataProviderType, servicePath) {
        if (dataProviderType === PROVIDER_TYPE_SERVER) {
            return new ServerStrategy(servicePath);
        } else {
            return new OtherStrategy();
        }
    }

    function createPlayCover(info, clickAction) {

        var playCover = MediasitePlayCover.create(Mediasite.Player.Localization.PlayCover);

        playCover.options.shouldShowTitle = true;
        playCover.options.shouldShowPlayButton = true;
        playCover.options.backgroundImageUrl = "Javascript/Players/SmartPlayer/images/default_slide.png";
        playCover.options.shouldDelayLiveUntilAirDate = info.IsLiveIndicationDelayed;

        playCover.title = info.Title;
        playCover.airDateUnixTime = (info.AirDateUnixTimeInMs + info.ServerClockSkew);
        playCover.presentationStatus = info.PlayStatus;

        playCover.thumbnailUrl = info.ThumbnailUrl;
        playCover.defaultThumbnailUrl = info.DefaultThumbnailUrl;

        playCover.clickAction = clickAction;

        return playCover;
    }


    function CrudeApi(thisWindow, otherWindow, allowedOrigins) {
        var self = this;

        var allowedOriginMatcher = Mediasite.Player.ApiOrigin.createOriginMatcherFromList(allowedOrigins);

        function isAllowedOrigin(origin) {
            return allowedOriginMatcher.match(origin);
        }

        window.isAllowedOrigin = isAllowedOrigin;

        function messageHandler(event) {
            var data, command;
            var origin = event && event.origin;

            if (!isAllowedOrigin(origin)) {
                return;
            }

            data = messageEventToMessageData(event);
            command = data && (typeof data.command === "string") && data.command;

            if (command === "setPlayCoverCustomHtml" && (typeof self.onSetPlayCoverCustomHtml === "function")) {
                htmlString = (data.params && data.params[0] && data.params[0].htmlString) || "";
                self.onSetPlayCoverCustomHtml(htmlString);
            }

        }

        function listenForMessages() {
            thisWindow.removeEventListener("message", messageHandler, false);
            thisWindow.addEventListener("message", messageHandler, false);
        }

        function raiseIFrameApiEvent(eventName) {
            if (otherWindow) {
                otherWindow.postMessage(JSON.stringify({ event: eventName, data: {} }), "*");
            }
        }

        function messageEventToMessageData(event) {
            var prefix = "MediasitePlayer:";
            var messageText = (event && event.data) || "";
            var jsonData;

            if (messageText.indexOf(prefix) !== 0) {
                return {};
            }

            jsonData = messageText.substring(prefix.length);
            return JSON.parse(jsonData);
        }


        self.raisePlayCoverReady = function () {
            raiseIFrameApiEvent("playcoverready");
        };

        self.raisePlayCoverClick = function () {
            raiseIFrameApiEvent("playcoverclick");
        };

        self.onSetPlayCoverCustomHtml = function (htmlString) { };


        listenForMessages();
    }


    function PlayCoverHelper(strategy) {
        var self = this;

        self.strategy = strategy || new OtherStrategy();

        self.getPlayCoverInfo = function (presentationId, callback) {
            var successCallback = function (playCoverInfo) {
                playCoverInfo.ThumbnailUrl = fixThumbnailUrl(presentationId, playCoverInfo.ThumbnailUrl);
                callback(playCoverInfo);
            };
            var failureCallback = function () { callback(null); };
            strategy.getPlayCoverInfo(presentationId, successCallback, failureCallback);
        }

        self.shouldShowPlayCover = function (playCoverInfo) {
            var qsOptions = self.getQueryStringOptions();

            if (!self.strategy.contextSupportsPlayCover) {
                return false;
            } else if (typeof qsOptions.enable === "boolean") {
                return qsOptions.enable;
            } else if (playCoverInfo.PlayCoverOnlyWhenEmbedded) {
                return SFMP.Utility.isEmbedded();
            } else {
                return true;
            }
        };

        self.makePlayCover = function (playCoverInfo, clickAction) {
            var defaultQueryStringValues = {
                enabled: null,
                showTitle: true,
                showPlayButton: true,
                showCountdown: playCoverInfo.IsLiveCountdownEnabled
            };
            var qsOptions, cover, thumbnailUrl;

            cover = createPlayCover(playCoverInfo, clickAction);

            qsOptions = self.getQueryStringOptions(defaultQueryStringValues);
            cover.options.shouldShowTitle = qsOptions.showTitle;
            cover.options.shouldShowPlayButton = qsOptions.showPlayButton;
            cover.options.shouldShowLiveCountdown = qsOptions.showCountdown;

            return cover;
        };

        self.makePresentationStatusGetter = function (presentationId) {
            return function (callback) {
                getPresentationStatus(presentationId, callback);
            };
        };

        self.getQueryStringOptions = function (defaults) {
            var qs = getQueryStringBoolOrDefault;
            var defaults = defaults || {};

            var options = {
                enable: qs(SFMP.Utility.queryStringParam.COVER_ENABLE, defaults.enable),
                showTitle: qs(SFMP.Utility.queryStringParam.COVER_TITLE, defaults.showTitle),
                showPlayButton: qs(SFMP.Utility.queryStringParam.COVER_PLAYBUTTON, defaults.showPlayButton),
                showCountdown: qs(SFMP.Utility.queryStringParam.COVER_COUNTDOWN, defaults.showCountdown)
            };

            // Don't break the deprecated param.
            if (typeof options.enable !== "boolean") {
                options.enable = qs(SFMP.Utility.queryStringParam.COVER_ENABLE_OLD, defaults.enable);
            }

            return options;
        };

        self.makeSetPlayCoverCustomHtmlCallback = function (playCover) {
            return function (htmlString) {
                playCover.customMessageHtml = SFMP.Utility.sanitizeHtmlString(htmlString);
            };
        }


        function getQueryStringBoolOrDefault(paramName, defaultValue) {
            var queryParam = SFMP.Utility.getQueryParam(paramName) || "";
            var qsParamTrue = (queryParam.toLowerCase() === "true");
            var qsParamFalse = (queryParam.toLowerCase() === "false");

            if (qsParamTrue || qsParamFalse) {
                return qsParamTrue;
            } else {
                return defaultValue;
            }
        }

        function fixThumbnailUrl(presentationId, url) {
            if (!url) {
                // Garbage in -- garbage out.
                return url;
            }

            var connector, collectionId, ticket;
            var fixed = url;

            function getConnector() { return (fixed.indexOf("?") > -1) ? "&" : "?" }
            
            collectionId = getCollectionIdFromQueryString();
            ticket = getEffectiveAuthTicket(presentationId, collectionId);

            if (ticket) {
                fixed += getConnector() + SFMP.Utility.queryStringParam.AUTHTICKET + "=" + ticket;
            }

            return fixed;
        }

        function getEffectiveAuthTicket(presentationId, collectionId) {
            var i, ticket;
            var ids = [];

            // The current collection's auth ticket gets firt priority.
            if (collectionId) {
                ids.push(collectionId);
            }

            // The presentation's auth ticket gets second priority.
            if (presentationId) {
                ids.push(presentationId);
            }

            for (i = 0; i < ids.length; i += 1) {
                ticket = SFMP.Utility.getAuthTicketFromCookie(ids[i]);
                if (ticket) {
                    // Found a ticket, so we're done.
                    return ticket;
                }
            }

            return null; // Failed to find a ticket.
        }
        
        function getCollectionIdFromQueryString() {
            // Array of query string params that *could* hold the collection id. 
            // The param earlier in the array wins, should more than one exist in the query string.
            var params = [SFMP.Utility.queryStringParam.COLLECTION, SFMP.Utility.queryStringParam.CATALOG];
            var i, value;
            var result = "";

            for (i = 0; i < params.length; i += 1) {
                value = SFMP.Utility.getQueryParam(params[i]);
                if (typeof value === "string" && value.length > 0) {
                    result = value;
                    break;
                }
            }

            return result;
        }

        function getPresentationStatus(presentationId, callback) {
            var successCallback = function (status) {
                callback(status);
            };
            var failureCallback = function () { 
                callback(null); 
            };
            strategy.getPresentationStatus(presentationId, successCallback, failureCallback);
        }
    }

    function createPlayCoverHelper(dataProviderType, servicePath) {
        var strategy = getPlayCoverStrategy(dataProviderType, servicePath);
        var helper = new PlayCoverHelper(strategy);
        return helper;
    }

    function createCrudeApi(thisWindow, otherWindow, allowedOrigins) {
        return new CrudeApi(thisWindow, otherWindow, allowedOrigins);
    };


    return {
        create: createPlayCoverHelper,
        createCrudeApi: createCrudeApi
    }

})();