﻿// Copyright 2007-2010 Panopto, Inc.
// All rights reserved.  Reuse and redistribution strictly prohibited.

/// <reference name="MicrosoftAjax.js"/>
/// <reference path="~/Scripts/jQuery/jquery-1.6.1.js" />

/// <reference path="~/Scripts/Panopto/GlobalResources.js"/>
/// <reference path="~/Scripts/Panopto/Data.js"/>
/// <reference path="~/Scripts/Panopto/Application.js"/>

Type.registerNamespace("Panopto");


// Default delivery name, hidden in display.
var c_defaultDeliveryName = "default";

Panopto.Util = function ()
{
    /// <summary>
    ///     Static methods to provide utility functions across pages.
    /// </summary>
}

// URL for JSON data service.
Panopto.Util.c_dataServiceUrl =
     Panopto.appRoot + "/Services/Data.svc";

// Wrap Sys.Net.WebServiceProxy to allow named parameters, use common defaults, and show loading indicators
//BUGBUG: JS Intellisense summary would be nice for required / optional params.
Panopto.Util.callWebMethod = function (params)
{
    // Empty set will not show indicator if client passes null
    var loadingIndicator = $();

    // Use passed in selector / element / etc. for loading indicator
    if (params.loadingIndicator)
    {
        loadingIndicator = $(params.loadingIndicator);
    }
    // If loadingIndicator is not specified, default to modal loading indicator (most common)
    else if ((params.loadingIndicator === undefined) && parent && parent.document)
    {
        loadingIndicator = $(".updating-settings", parent.document);
    }

    loadingIndicator.show();

    Sys.Net.WebServiceProxy.invoke(
        // Default to data service unless serviceURL is specified
        params.serviceURL || Panopto.Util.c_dataServiceUrl,
        params.methodName,
        // useGet=false => POST
        false,
        params.params,
        // onSuccess
        function (data)
        {
            if (params.onSuccess)
            {
                params.onSuccess(data);
            }

            loadingIndicator.hide();
        },
        // onFailure
        function (e)
        {
            if (params.onFailure)
            {
                params.onFailure(e);
            }

            loadingIndicator.hide();
        });
};

Panopto.Util.showIndicatorForDataContextSave = function (dataContext)
{
    var loadingIndicator = $(".updating-settings", ((parent && parent.document) ? parent.document : null));

    loadingIndicator.show();

    dataContext.set_handleSaveChangesResultsMethod(function ()
    {
        loadingIndicator.hide();
    });
};   

Panopto.Util.displayDeliveryName = function (deliveryItem)
{
    /// <summary>
    ///     Format delivery name for display.
    ///     Hide "default", otherwise wrap in "()" and display.</summary>
    /// <param name="deliveryItem" type="Object">
    ///     The item containing delivery information.</param>
    /// <returns type="String" />

    var deliveryName = deliveryItem.DeliveryName;

    return (deliveryName && (deliveryName != c_defaultDeliveryName))
                ? String.format("{0} ({1})", deliveryItem.SessionName, deliveryName)
                : deliveryItem.SessionName;
}

Panopto.Util.displayUserName = function (userItem)
{
    var displayName = userItem.UserKey;

    if (userItem.FullName)
    {
        displayName = String.format("{0} ({1})", userItem.FullName, userItem.UserKey);
    }

    return displayName;
}

Panopto.Util.displayFullNameAndEmail = function (fullName, email, textOnly)
{
    var output = "";

    if (textOnly)
    {
        fullName = Panopto.Util.innerText(fullName);
        email = Panopto.Util.innerText(email);
    }

    if (fullName)
    {
        output = fullName;

        if (email)
        {
            if (textOnly)
            {
                output += String.format(" <{0}>", email);
            }
            else
            {
                output += String.format(" &lt;{0}&gt;", email);
            }
        }
    }
    else
    {
        // Convert null to "" for IE
        output = email || "";
    }

    return output;
}

Panopto.Util.dateFromJSON = function (jsonDate)
{
    /// <summary>
    ///     Converts a JSON date string like "\/Date(19052342384-170297)\/" to a date.
    /// </summary>

    if (!jsonDate)
    {
        return null;
    }

    var dateString = jsonDate.toString(); // sometimes the JSON string is an object

    // create a string that is "new Date()" by removing the beginning and trailing "/" and adding new
    // then we can just evaluate the string as javascript
    var dateConstructorScript = "new " + dateString.substring(1, dateString.length - 1);
    return eval(dateConstructorScript);
}

Panopto.Util.dateToUtc = function (date)
{
    /// <summary>
    ///     Converts a date to a UTC date object.
    /// </summary>

    // getTime() returns milliseconds since 1970 UTC + local offset
    var localTime = date.getTime();
    
    // getTimeZoneOffset() returns offset in seconds, convert to milliseconds
    var localOffset = date.getTimezoneOffset() * 60 * 1000;

    return new Date(localTime + localOffset);
}

Panopto.Util.displayDate = function (date, binding)
{
    /// <summary>
    ///     Display a date like "Tue, 2/16/2010 5:00 PM" (locale-specific).
    ///       binding.format = "time" returns just the time portion
    ///       binding.format = "long" returns the whole date instead of 2/16/2010 portion
    ///       binding.local = true returns the date in brower-specific time; false/null is UTC
    /// </summary>

    var displayDate = Panopto.GlobalResources.None;

    if (date)
    {
        if (!binding || !binding.local)
        {
            date = Panopto.Util.dateToUtc(date);
        }

        if (binding && (binding.format == "time"))
        {
            displayDate = date.localeFormat("t");
        }
        else if (binding && (binding.format == "long"))
        {
            displayDate = date.localeFormat("ddd") + ", " + date.localeFormat("d") + " " + date.localeFormat("t");
        }
        else
        {
            displayDate = date.localeFormat("d");
        }
    }

    return displayDate;
}

Panopto.Util.displayTime = function (date, binding)
{
    /// <summary>
    ///     Display the time portion of a date in a locale-specific way.
    /// </summary>

    var displayTime = Panopto.GlobalResources.n_a;

    if (date)
    {
        if (binding && binding.utc)
        {
            date = Panopto.Util.dateToUtc(date);
        }

        displayTime = date.localeFormat("t");
    }

    return displayTime;
}

Panopto.Util.displayDuration = function (duration)
{
    ///	<summary>
    ///		Format seconds into "1h 01m 00s" format.</summary>
    ///	<param name="duration" type="Number">
    ///		The duration in seconds.</param>
    ///	<returns type="String" />

    if (duration)
    {
        var hours = Math.floor(duration / 3600);
        var minutes = Math.floor((duration / 60) - (hours * 60));
        var seconds = Math.floor(duration % 60);

        if (hours)
        {
            durationString = String.format("{0}h {1}m {2}s", hours, Panopto.Util.pad2(minutes), Panopto.Util.pad2(seconds));
        }
        else if (minutes)
        {
            durationString = String.format("{0}m {1}s", minutes, Panopto.Util.pad2(seconds));
        }
        else
        {
            durationString = String.format("{0}s", seconds);
        }
    }
    else
    {
        // Return "n/a" for null durations.
        var durationString = Panopto.GlobalResources.n_a;
    }

    return durationString;
}

Panopto.Util.displayGB = function (gigabytes)
{
    return (gigabytes).localeFormat("N02") + " GB";
}

// Affiliation name is optional, for producing site-relative links from hosted master site.
// Relative URL should be - app-relative, not site relative (don't include application path)
Panopto.Util.getAbsoluteUrl = function (relativeUrl, affiliationName)
{
    var webServerFQDN = affiliationName
        ? affiliationName + "." + Panopto.hostedSuffix
        : Panopto.webServerFQDN;

    return 'http://' + webServerFQDN + Panopto.appRoot + relativeUrl;
}

Panopto.Util.focusElement = function (elementID)
{
    var element = $get(elementID);

    if (element)
    {
        // IE doesn't like to focus synchronously.
        setTimeout(function () { element.focus(); }, 0);
    }
}

// serialize an object with the given parameter format.
Panopto.Util.serializeObjectToString = function (paramObject, parameterFormat, separator)
{
    var resultString = "";

    if (typeof paramObject == "object") {
        // Build array of query params
        var paramArray = [];
        $.each(paramObject, function (key, value) {
            paramArray.push(String.format(parameterFormat, key, value));
        });

        resultString = paramArray.join(separator);
    }

    return resultString;
}

// serialize to query params.
Panopto.Util.serializeObjectToQueryString = function (paramObject) 
{
    return Panopto.Util.serializeObjectToString(paramObject, "{0}={1}", "&");
}

// serialize to Silverlight InitParams.
Panopto.Util.serializeObjectToInitParams = function (paramObject) 
{
    return Panopto.Util.serializeObjectToString(paramObject, "{0}={1}", ",");
}

Panopto.Util.pad2 = function (num)
{
    ///	<summary>
    ///		Pad number to two digits.</summary>
    ///	<param name="num" type="Number">
    ///		The duration in seconds.</param>
    ///	<returns type="String" />

    return (num >= 10)
        ? num
        : "0" + num;
}

Panopto.Util.getThumbnailUrl = function (item)
{
    return (item.Context && (item.Context.length > 0) && item.Context[0].ThumbUrl)
        ? item.Context[0].ThumbUrl
        : item.ThumbUrl;
}

Panopto.Util.getViewerLink = function (item, time)
{
    var relativeUrl = "/Pages/Viewer/Default.aspx?id=" + item.DeliveryID + (time ? "&start=" + time : "");

    return Panopto.Util.getAbsoluteUrl(relativeUrl, item.AffiliationName);
}

// Mark the modal for host UI update on close
Panopto.Util.flagModal = function()
{
    var modalInstance = parent.Panopto.ModalPopup.defaultInstance;

    modalInstance.hasChanges = true;
}

// Close modal
Panopto.Util.closeModal = function (hasChanges)
{
    // Get modal instance from page hosting modal iframe.
    var modalInstance = parent.Panopto.ModalPopup.defaultInstance;

    // Flag new changed state without overwriting existing one.
    modalInstance.hasChanges = modalInstance.hasChanges || hasChanges;

    // Close modal, updating host UI as necessary.
    parent.Panopto.Application.defaultInstance.updateState({
        modalPage: null,
        modalHeader: null,
        modalParams: null
    });
}

Panopto.Util.handleResize = function (isList)
{
    // calculate the browser's window height and set column div height accordingly
    var windowWidth = $(window).width();
    var windowHeight = $(window).height();

    var cTopChromeHeight = 72;

    // Don't clip interface to screen size on Mobile Safari, since scrollable DIVs don't work right.
    if (!Panopto.browser.isMobileSafari)
    {
        var leftcolheight = windowHeight - cTopChromeHeight;
        $('.leftcolumn').css('height', leftcolheight);

        if (isList)
        {
            var cRightColumnHeaderHeight = 123;
            var cFilterBarHeight = 35;
            var cPagingHeight = 36;

            var rightcolheight = windowHeight - cTopChromeHeight - cRightColumnHeaderHeight - cPagingHeight;

            $('.content-table').css('height', rightcolheight);
        }
    }

    // update modal boundaries
    var cModalWidthPadding = 100;
    var cModalHeightPadding = 200;

    $get("modalIframe").style.maxWidth = windowWidth - cModalWidthPadding + 'px';
    $get("modalIframe").style.maxHeight = windowHeight - cModalHeightPadding + 'px';
}

Panopto.Util.isViewable = function (sessionRow)
{
    return ((sessionRow.Status == Panopto.Data.SessionStatus.Complete)
            || (sessionRow.Status == Panopto.Data.SessionStatus.Live));
}

Panopto.Util.innerText = function (markup)
{
    /// <summary>Strips HTML markup from an HTML string.</summary>

    // Handle IE conversion of null/undefined to "null"/"undefined".
    markup = (markup == null) ? "" : markup;

    // wrap page name in a span and then use .text() to get the innerHTML
    // this will ignore any markup in the page name
    return $("<span>" + markup + "</span>").text();
}

// Compare two arrays, order matters.  Doesn't deep compare non-scalar items.
Array.equals = function (array1, array2)
{
    // Refs are equal
    if (array1 === array2)
    {
        return true;
    }
    // If either is null, and ref compare doesn't match, then they aren't both null.
    if ((array1 == null) || (array2 == null))
    {
        return false;
    }
    // Check for equal lengths.
    else if (array1.length != array2.length)
    {
        return false;
    }

    // Compare arrays item-by-item.
    var match = true;
    $.each(array1, function (index, value)
    {
        if (array1[index] != array2[index])
        {
            match = false;
            return false;
        }
    });

    return match;
};


//Register with MicrosoftAjax Type model after class is defined.
Panopto.Util.registerClass('Panopto.Util');

