/*global Mediasite :true*/
if (typeof Mediasite === "undefined" || !Mediasite) {
    var Mediasite = {};
}

Mediasite.namespace = function () {
    var a = arguments, o = null, i, j, d;
    for (i = 0; i < a.length; i = i + 1) {
        d = (a[i].toString()).split(".");
        o = Mediasite;

        for (j = (d[0] === "Mediasite") ? 1 : 0; j < d.length; j = j + 1) {
            o[d[j]] = o[d[j]] || {};
            o = o[d[j]];
        }
    }
    return o;
};

Mediasite.Slide = function (number, time, text, description) {
    this.Number = number;
    this.Time = time;
    this.Text = text;
    this.Description = description;
};
Mediasite.Slide._cacheFriendlySlideHeights = [64, 128, 256, 512, 768];
Mediasite.Slide.getCacheFriendlyImageSize = function(desiredHeight, aspect) {
    var i;
    for (i = 0; i < Mediasite.Slide._cacheFriendlySlideHeights.length; i++) {
        var height = Mediasite.Slide._cacheFriendlySlideHeights[i];
        if (desiredHeight <= height) {
            return new Mediasite.Geometry.Size(Math.round(height * aspect), height);
        }
    }

    return Mediasite.Geometry.Size.Zero();
}

Mediasite.Chapter = function (number, time, text) {
    this.Number = number;
    this.Time = time;
    this.Text = text;
};

Mediasite.Link = function (url, description) {
    this.Url = url;
    this.Description = description;
};

Mediasite.Presenter = function (name, imageUrl, email, bioUrl) {
    this.Name = name;
    this.ImageUrl = imageUrl;
    this.Email = email;
    this.BioUrl = bioUrl;
};

Mediasite.TimingEventType = {
    Caption: 1,
    OcrText: 2
};


Mediasite.Presentation = function (manifest) {
    this.PlaybackTicketId = manifest.PlaybackTicketId;
    this.PresentationId = manifest.PresentationId;
    this.Title = manifest.Title;
    this.Description = manifest.Description;
    this.Date = manifest.AirDate;
    this.Time = manifest.AirTime;
    this.Duration = manifest.Duration;
    this.Presenters = manifest.Presenters;
    this.Links = manifest.SupportingLinks;
    this.Chapters = manifest.Chapters;
    this.HasCaptions = manifest.Transcript.length > 0;
    this.IsStandAlone = manifest.IsStandAlone;
    this.SearchPresentationTextOnServer = manifest.SearchPresentationTextOnServer;
    this.IsOnDemand = manifest.IsOnDemand;
    this.ServerVersion = manifest.Version;
    this.ForumEnabled = manifest.ForumEnabled;
    this.SharingEnabled = manifest.SharingEnabled;
    this.PollingEnabled = manifest.PollingEnabled;
    this.PollingLocation = manifest.PollingLocation;
    this.PlayStatus = manifest.PlayStatus;
    this.HasSlideContent = manifest.HasSlideContent;
    this.Transcript = manifest.Transcript;

    $.each(this.Transcript, function addTypeToTranscriptEvents(index, item) {
        item.Type = Mediasite.TimingEventType.Caption;
    });

    function fillSlides() {
        var i, slides = [];

        for (i = 0; i < manifest.Slides.length; i++) {
            slides[i] = new Mediasite.Slide(i + 1,
                        manifest.Slides[i].Time,
                        manifest.Slides[i].Text,
                        manifest.Slides[i].Description);
        }
        return slides;
    }

    function fillMediaUrls() {
        var i, media = manifest.VideoUrls;

        for (i = 0; i < media.length; i++) {
            if (media[i].CanChangeScheme === true && window.location.protocol !== media[i].Location.toLowerCase().substr(0, window.location.protocol.length)) {
                media[i].Location = window.location.protocol + media[i].Location.substr(media[i].Location.indexOf(':') + 1);
            }
        }
        return media;
    }

    this.MediaUrls = fillMediaUrls();
    this.Slides = fillSlides();

    this.GetSlideUrl = function (slideNumber, width, height) {

        slideNumber = slideNumber.toString();
        while (slideNumber.length < 4) {
            slideNumber = '0' + slideNumber;
        }

        var slideFileName = "slide_" + slideNumber + "_full.jpg";
        if (arguments.length === 3 && !manifest.IsStandAlone) {
            slideFileName = slideFileName.replace(/full/i, width + "_" + height);
        }

        var source = manifest.SlideBaseUrl + slideFileName;
        if (manifest.AnonymousAllowed === false && manifest.SlidePlaybackTicketId && manifest.SlidePlaybackTicketId.length > 0) {
            if (source.indexOf('?') > -1) {
                source += '&playbackTicket=' + manifest.SlidePlaybackTicketId;
            }
            else {
                source += '?playbackTicket=' + manifest.SlidePlaybackTicketId;
            }
        }

        return source;
    };

    this.GetCacheFriendlySlideUrl = function (slideNumber, height, aspect) {
        var size = Mediasite.Slide.getCacheFriendlyImageSize(height, aspect);
        if (size.width() > 0) {
            return this.GetSlideUrl(slideNumber, size.width(), size.height());
        } else {
            return this.GetSlideUrl(slideNumber);
        }
    };

};

Mediasite.namespace("BrowserDetect");

/* Environment */
Mediasite.BrowserDetect.Embedded = function () {
    return top !== self;
};

Mediasite.BrowserDetect.Local = function () {
    return !!/file/i.exec(location.protocol);
}

/* Functionality support */

Mediasite.BrowserDetect.Touch = function () {
    return window.Modernizr.touch;
}

/* Browser */

Mediasite.BrowserDetect.IOS = function () {
    return !!/iphone|ipod|ipad/i.exec(navigator.userAgent);
};

Mediasite.BrowserDetect.IOS5 = function () {
    return Mediasite.BrowserDetect.IOS() && /OS 5_/.exec(navigator.userAgent);
};

Mediasite.BrowserDetect.IOS4 = function () {
    return Mediasite.BrowserDetect.IOS() && /OS 4_/.exec(navigator.userAgent);
};

Mediasite.BrowserDetect.Android = function () {
    return !!/android|crmo/i.exec(navigator.userAgent);
};

Mediasite.BrowserDetect.InternetExplorer = function () {
    if ($.browser.msie) {
        return $.browser.version;
    }

    return false;
};

Mediasite.BrowserDetect.Chrome = function () {
    if (/chrome/i.exec(navigator.userAgent)) {
        return $.browser.version;
    }

    return false;
};

Mediasite.BrowserDetect.MacOS10DotWhat = function () {
    var matches = navigator.userAgent.match(/mac os x (\d+)_(\d+)/i);
    if (matches && matches.length == 3) {
        return Number(matches[2]);
    } else {
        return -1;
    }
};

Mediasite.BrowserDetect.MacOSX = function () {
    return Mediasite.BrowserDetect.MacOS10DotWhat() > -1;
};

Mediasite.BrowserDetect.Safari = function () {
    // Chrome mentions Safari in its UA string.
    return /safari/i.exec(navigator.userAgent) && !Mediasite.BrowserDetect.Chrome();
};

Mediasite.BrowserDetect.MacSafari = function () {
    return Mediasite.BrowserDetect.Safari() && Mediasite.BrowserDetect.MacOSX();
};

Mediasite.BrowserDetect.Blackberry = function () {
    if (/blackberry|rim/i.exec(navigator.userAgent)) {
        return $.browser.version;
    }

    return false;
};


Mediasite.BrowserDetect.Mobile = function () {
    return !!(Mediasite.BrowserDetect.IOS() || Mediasite.BrowserDetect.Android() || Mediasite.BrowserDetect.Blackberry());
};

/* --- end Mediasite.BrowserDetect --- */


Mediasite.GetQueryParam = function (name) {
    var regexS = "[\\?&]" + name + "=([^&#]*)";
    var regex = new RegExp(regexS, "i");
    var results = regex.exec(window.location.href);
    if (results === null) {

        return "";
    }
    else {
        return decodeURIComponent(results[1].replace(/\+/g, " "));
    }
};

Mediasite.Cookie = function (name) {
    var valueDelimiter = "&";
    var values = {};
    var expires = null;
    var path = null;

    function readCookieData() {
        var i, parts;
        if (document.cookie) {
            var begin = document.cookie.indexOf(name + "=");
            if (begin !== -1) {
                begin += name.length + 1;
                var end = document.cookie.indexOf(";", begin);
                if (end === -1) {
                    end = document.cookie.length;
                }

                var rawCookie = document.cookie.substring(begin, end);
                var entries = rawCookie.split(valueDelimiter);

                for (i = 0; i < entries.length; i++) {
                    parts = entries[i].split("=");

                    if (parts.length === 2) {
                        values[parts[0]] = decodeURIComponent(parts[1]);
                    }
                }
            }
        }
    }

    readCookieData();

    function writeCookieData() {
        var key, now, newCookie;
        if (!expires) {
            now = new Date();
            expires = new Date(now.getFullYear() + 1, now.getMonth(), now.getDate());
        }

        var cookieData = "";
        for (key in values) {
            if (values.hasOwnProperty(key)) {
                cookieData += key + "=" + encodeURIComponent(values[key]) + valueDelimiter;
            }            
        }
        cookieData = cookieData.substring(0, cookieData.length - 1);

        newCookie = name + "=" + cookieData +
            ((path) ? "; path=" + path : "") +
		    ((expires) ? "; expires=" + expires.toGMTString() : "");

        document.cookie = newCookie;
    }

    this.GetName = function () {
        return name;
    };

    this.GetExpires = function () {
        return expires;
    };

    this.SetExpires = function (date) {
        expires = date;
    };

    this.GetPath = function () {
        return path;
    };

    this.SetPath = function (p) {
        path = p;
    };

    this.SetValue = function (name, value) {
        values[name] = value;
        writeCookieData();
    };

    this.GetValue = function (name, def) {
        if (!values[name]) {
            return def;
        }
        return values[name];
    };

    this.GetNumberValue = function (name, def) {
        if (!values[name]) {
            return def;
        }
        return Number(values[name]);
    };

    this.GetBoolValue = function (name, def) {
        if (!values[name]) {
            return def;
        }
        if (values[name].toLowerCase() === "true") {
            return true;
        }
        else {
            return false;
        }
    };
};

Mediasite.Urls = (function (window, $, undefined) {
    var module = {};

    module.EscapedUnicodeRegex = /\%u([0-9A-F]{4})/g;
    module.UnicodeHtmlEntityReplacement = "&#x$1;"

    module.EscapeForMailto = function (val) {
        /// Escape the string, then fix escaped Unicode references for mailto 

        var useHtmlEntities = false;

        var msieVersion = Mediasite.BrowserDetect.InternetExplorer();
        if (msieVersion && msieVersion <= 6) {
            useHtmlEntities = true;
        }


        var escaped = escape(val);

        if (useHtmlEntities) {
            // http://blogs.msdn.com/b/ie/archive/2007/02/12/international-mailto-uris-in-ie7.aspx
            var escapedAndFixed = escaped.replace(module.EscapedUnicodeRegex, module.UnicodeHtmlEntityReplacement);
        } else {
            var escapedAndFixed = escaped.replace(module.EscapedUnicodeRegex, function (match) {
                return encodeURI(unescape(match));
            });
        }

        return escapedAndFixed;
    }

    module.ContainsUnicode = function (url) {
        var decodedUri = escape(decodeURI(url));
        if (module.EscapedUnicodeRegex.test(decodedUri)) {
            return true;
        }

        return false;
    }

    return module;
})(this, jQuery);


Mediasite.Debug = (function () {
    var module = {};

    // ----- Enabling -----
    module.Enabled = false;

    // ----- Logging -----

    function prepareLogMessage(args) {
        var message = "";
        for (var i = 0, len = args.length; i < len; i++) {
            if (i > 0) message += " ";
            message += args[i];
        }

        return message;
    }

    module.Log = function () {
        if (!module.Enabled) return;

        var message = prepareLogMessage(arguments);

        if (window.console && console.log) {
            console.log(message);
        }

        return message;
    };

    module.Warn = function () {
        if (!module.Enabled) return;

        var message = prepareLogMessage(arguments);

        if (window.console) {
            if (console.warn) {
                console.warn(message);
            } else if (console.log) {
                console.log("WARN: " + message);
            }
        }

        return message;
    };

    module.Error = function () {
        if (!module.Enabled) return;

        var message = prepareLogMessage(arguments);

        if (window.console) {
            if (console.error) {
                console.error(message);
            } else if (console.log) {
                console.log("ERROR: " + message);
            }
        }

        return message;
    };

    module.LogEvent = function (evt, evtThis, msg) {
        /// <summary>Log an event</summary>
        /// <param name="evt" type="Event">The event in question</param>
        /// <param name="evtThis" type="DOM">The event handler's `this`</param>
        /// <param name="msg" type="String">Extra text to append to the first line of the log</param>

        if (!module.Enabled) return;

        module.Log(evt.type, (msg ? msg : ''),
                                         '\n   Target:  ' + evt.target.nodeName.toString().toLowerCase() + '#' + evt.target.id,
                    (evt.relatedTarget ? '\n   Related: ' + evt.relatedTarget.nodeName.toString().toLowerCase() + '#' + evt.relatedTarget.id : ''),
                    (evtThis ? '\n   This:    ' + evtThis.nodeName.toString().toLowerCase() + '#' + evtThis.id : ''));
    };


    // ----- Data Repository -----

    var dataRepository = {};

    module.Store = function (key, value) {
        /// <summary>Store a value by name in a globally-accessible repository.</summary>
        /// <param name="key" type="number|string">Identifier for value</param>
        /// <param name="value">Value to store</param>
        /// <returns>`value`</returns>

        if (!module.Enabled) return;

        if (typeof key === "number" || typeof key === "string") {
            dataRepository[name] = value;
        }

        return value;
    };

    module.Fetch = function (key) {
        /// <summary>Fetch a value by name from a globally-accessible repository</summary>
        /// <param name="name" type="number|string">Identifier for value</param>
        /// <returns>If `name` has been stored previously, the last stored value; otherwise, null</returns>

        if (!module.Enabled) return;

        var value = null;
        if (key !== null && typeof key !== "undefined" && dataRepository.hasOwnProperty(key)) {
            value = dataRepository[key];
        }

        return value;
    };

    return module;
})();

String.prototype.replaceholders = function () {
    /// <summary>Replace placeholders in a format string.
    /// <para>this (the string) should be in the format "foo %%0%% %%1%%".</para>
    /// <para>Example: "%%0%% foo %%1%% %%0%%".replaceholders("baz", "bar") returns "baz foo bar baz".</para>
    /// </summary>

    var replaced = this + ""; // Clone original string 
    if (this && this.length > 0) {
        for (var i = 0, len = arguments.length; i < len; i++) {
            var search = new RegExp('%%' + i + '%%', 'g');
            var replace = arguments[i];
            replaced = replaced.replace(search, replace);
        }
    }

    return replaced;
};
