﻿// Copyright 2007-2010 Panopto, Inc.
// All rights reserved.  Reuse and redistribution strictly prohibited.

/// <reference name="MicrosoftAjax.js" />
/// <reference path="~/Scripts/MicrosoftAjax/Start.debug.js" />
/// <reference path="~/Scripts/jQuery/jquery-1.6.1.js" />

/// <reference path="~/Scripts/Panopto/Data.js"/>
/// <reference path="~/Scripts/Panopto/Util.js"/>
/// <reference path="~/Scripts/Panopto/Application.js"/>


Type.registerNamespace("Panopto");


Panopto.ModalPopup = function ()
{
    // Global namespaced ref to singleton modal instance.
    Panopto.ModalPopup.defaultInstance = this;

    Sys.converters.displayModalPageName = this._getPageName;

    // Modal component requires a target element at create time, so just point at a hidden dummy element.
    this._modalPopup = Sys.create.modalPopup("#modalDummyTarget",
    {
        PopupControlID: "modalWindow",
        BackgroundCssClass: "modalBackground"
    });

    // Navigation links list, populated per page type on modal display.
    this._modalNavigationDataview = Sys.create.dataView("#modalNavigation",
    {
        // Decorate item ID with page name and wire up click handler.
        itemRendered: Function.createDelegate(this, function (sender, args)
        {
            var data = args.dataItem,
                item = args.get("li");

            item.id = "modalLink-" + data.Name;

            // Hide tabs based on role and hosted master
            if ((data.HideOnMaster && Panopto.isHostedMaster)
                || ((data.RequiredRole == Panopto.Data.AclRoleType.Admin)
                    && !Panopto.user.isAdmin)
                || ((data.RequiredRole == Panopto.Data.AclRoleType.Creator)
                    && (!Panopto.user.isCreator && !Panopto.user.isVideographer)))
            {
                item.style.display = "none";
            }

            $addHandler(item, "click", Function.createDelegate(this, function (e)
            {
                Panopto.Application.defaultInstance.updateState({ modalPage: data.Name });

                e.preventDefault();
            }));
        })
    });

    $addHandler($get("closeLink"), "click", Function.createDelegate(this, function (e)
    {
        Panopto.Application.defaultInstance.updateState({
            modalPage: null,
            modalHeader: null,
            modalParams: null
        });

        e.preventDefault();
    }));

    // Close modal popup on [Esc]
    $addHandler(document, "keydown", Function.createDelegate(this, function (e)
    {
        if (e.keyCode == Sys.UI.Key.esc)
        {
            Panopto.Application.defaultInstance.updateState({
                modalPage: null,
                modalHeader: null,
                modalParams: null
            });
        }
    }));

    // wire up onload handler for iframes
    $("#modalIframe").load(function ()
    {
        // since the iframe will fill the parent size, reset size to get an accurate measure on the iframe
        Panopto.ModalPopup.defaultInstance.resize(0, 0);

        // try to size the modal to the total iframe size (plus some padding to prevent unnecessary scrollbars)
        // Util.handleResize sets a max width and height based on the size of the browser to stop this from getting too big
        var scrollbarPadding = 30;

        try
        {
            Panopto.ModalPopup.defaultInstance.resize(
                this.contentWindow.document.documentElement.scrollWidth + scrollbarPadding,
                this.contentWindow.document.documentElement.scrollHeight + scrollbarPadding);
        }
        catch (e)
        {
            // protect against SSL boundary failures on resize.
        }

        // Make sure we're actively displaying a page.
        // Keeps initial iframe load from clobbering list load indicator.
        // Use static class ref because we need jQuery's this reference to IFRAME.
        if (Panopto.ModalPopup.defaultInstance._page)
        {
            // hide loading message
            $("#loadingMessage").fadeOut("fast");
        }
    });

    // Wire up navigate handler.
    // Call to add_navigate immediately fires handler with current state.
    // Probably should be the last call since this will fire a modal load.
    Panopto.Application.defaultInstance.add_navigate(Function.createDelegate(this, this._handleNavigate));
}

Panopto.ModalPopup.prototype =
{
    // Host UI can register for updates by setting an opener with an updateData() function.
    //BUGBUG: This should be a custom event.
    opener: null,
    _modalPopup: null,
    _page: null,
    _pageSet: null,
    _modalNavigationDataview: null,

    // Info about selected item in list.
    _selectedItemName: null,
    _queryParams: null,

    // Populate modal navigation links with links relevant to current item.
    _setPageSet: function (pageSet)
    {
        // Only update navigation links if pageSet has changed.
        if (this._pageSet != Panopto.ModalPopup.pageSets[pageSet])
        {
            this._pageSet = Panopto.ModalPopup.pageSets[pageSet];

            // Localize page set name.
            var pageSetDisplayName = Panopto.ModalPopup.getPageSetDisplayName(this._pageSet);

            // Set page set header text and class.
            $("#modalType").text(pageSetDisplayName);
            $("#modalType").attr("class", "modal-description " + this._pageSet.modalClass);

            if (!$("#modalHeader").text())
            {
                // if the item header text is empty, just use the page set display name
                $("#modalHeader").text(pageSetDisplayName || "");
            }

            // Only display nav links if there are more than one.
            if (this._pageSet.pages.length > 1)
            {
                this._modalNavigationDataview.set_data(this._pageSet.pages);
                this._modalNavigationDataview.refresh();
                $("#modalNavigation").show();
            }
            //BUGBUG: Adjust left margin.
            else
            {
                $("#modalNavigation").hide();
            }
        }
    },

    // Pop up modal dialog with specified page, storing and display specified item name and queryParams (hash from names to values).
    show: function (page, selectedItemName, queryParams)
    {
        this._page = page;
        this._selectedItemName = selectedItemName;
        this._queryParams = queryParams;

        // Set item header text.
        $("#modalHeader").text(this._selectedItemName || "");

        // Clear out div content placeholder.
        $("#modalContentPlaceholder").empty();

        // Display DIV
        if (page.indexOf("#") == 0)
        {
            // Get div element.
            var modalContentDiv = $(page);

            // Append a copy of the specified div to the content placeholder.
            $(modalContentDiv).clone().appendTo($("#modalContentPlaceholder")).show();

            // Show DIV content.
            this._displayDiv(true);
        }
        // Display page
        else
        {
            // Unauthenticated users can't view any iframe-based modal, redirect through login.
            if (!Panopto.user.isAuthenticated)
            {
                location.href = Panopto.appRoot
                        + "/Pages/Auth/Login.aspx?ReturnUrl="
                        + encodeURIComponent(location.href);
            }

            // Display navigation links for page set to which page belongs.
            for (pageSet in Panopto.ModalPopup.pageSets)
            {
                if (Panopto.ModalPopup.isInSet(pageSet, page))
                {
                    this._setPageSet(pageSet);
                    break;
                }
            }

            // If we don't have a suitable title, use the page set display name.
            // Don't do this before _setPageSet, since this._pageSet might be outdated.
            if (!$("#modalHeader").text())
            {
                var pageSetDisplayName = Panopto.ModalPopup.getPageSetDisplayName(this._pageSet);
                $("#modalHeader").text(pageSetDisplayName || "");
            }

            // Load specified page in modal's iframe.
            this._setPage(page);

            // Show iframe content.
            this._displayDiv(false);
        }

        this._modalPopup.show();
    },

    _displayDiv: function (isShown)
    {
        if (isShown)
        {
            // Clear item header class.
            $("#modalHeader").attr("class", "");

            // Clear page set header text and class.
            $("#modalType").text("");
            $("#modalType").attr("class", "");

            // Hide tabs.
            $("#modalNavigation").hide();

            // Hide iframe.
            $("#modalIframe").hide();
        }
        else
        {
            // Set item header class.
            $("#modalHeader").attr("class", this._pageSet.itemClass);

            // Show iframe.
            $("#modalIframe").show();
        }
    },

    hide: function ()
    {
        /// <summary>
        /// Close modal, updating host UI if requested by client page.
        /// </summary>

        this._page = null;

        this._modalPopup.hide();

        if (this.hasChanges && this.opener && this.opener.updateData)
        {
            this.opener.updateData();
        }

        // Clear flag.
        this.hasChanges = false;

        // Blank out iframe
        // location.replace() to avoid clobbering forward history.
        $get("modalIframe").contentWindow.location.replace("about:blank");
    },

    resize: function (width, height)
    {
        if (this._page)
        {
            $("#modalIframe").width(width);
            $("#modalIframe").height(height);

            // call show again to center the modal
            this._modalPopup.show();
        }
    },

    // Switch pages within the current set.
    _setPage: function (page)
    {
        // Keep track of current page for state diffs.
        this._page = page;

        // Find the data for the current page within the current page set's page list.
        var pageData = $.grep(this._pageSet.pages, function (item) { return (item.Name == page); })[0];

        // Un-highlight currently selected item.
        $("#modalNavigation li").removeClass("selected");

        // Highlight new selected item.
        $("#modalLink-" + page).addClass("selected");

        // Show "Loading..." message while iframe is loading
        $("#loadingMessage").show();

        // Build URL to target page.
        var url = this._pageSet.baseUrl + pageData.URL;

        if (this._queryParams)
        {
            url += "?" + this._queryParams;

            //HACKHACK: This is the one grouped page that has different params than its siblings.
            if (this._page == "SessionShare")
            {
                url += "&isFolder=false";
            }
        }

        // Populate iframe with URL of clicked link.
        // location.replace() to avoid clobbering forward history.
        $get("modalIframe").contentWindow.location.replace(url);
    },

    _getPageName: function (page)
    {
        return Panopto.LocalResources.ModalPopup[page + "DisplayName"] || page;
    },

    // Configure modal based on application state.
    _handleNavigate: function (sender, args)
    {
        var appState = args.get_state();
        
        if ((appState.modalPage != this._page) || (appState.modalHeader != this._selectedItemName) || (appState.modalParams != this._queryParams))
        {
            if (appState.modalPage != null)
            {
                this.show(appState.modalPage, appState.modalHeader, appState.modalParams);
            }
            else
            {
                this.hide();
            }
        }
    }
}

// Navigation links for various types of items the modal can display.
// Page lists are arrays so we can bind them (otherwise would use hash).
// Titles are strings because global resources haven't been bound yet.
Panopto.ModalPopup.pageSets =
{
    CreateSessionLinks:
    {
        title: "CreateSessionDisplayName",
        modalClass: "createSession",
        baseUrl: Panopto.appRoot + "/Pages/Sessions/",
        pages:
        [
            { Name: "CreateSession", URL: "Create.aspx" }
        ]
    },
    EditSessionLinks:
    {
        title: "EditSession",
        modalClass: "editModal",
        baseUrl: Panopto.appRoot + "/Pages/Editor/",
        pages:
        [
            { Name: "EditSession", URL: "ManageDeliveries.aspx" }
        ]
    },
    SessionLinks:
    {
        title: "SessionSettings",
        modalClass: "sessionSettings",
        itemClass: "session",
        baseUrl: Panopto.appRoot + "/Pages/",
        pages:
        [
            { Name: "SessionInfo", URL: "Sessions/Info.aspx" },
            { Name: "SessionShare", URL: "Share/Default.aspx", HideOnMaster: true },
            { Name: "SessionOutputs", URL: "Sessions/Outputs.aspx" },
            { Name: "SessionContents", URL: "Sessions/Contents.aspx", RequiredRole: Panopto.Data.AclRoleType.Creator },
            { Name: "SessionManage", URL: "Sessions/Manage.aspx", RequiredRole: Panopto.Data.AclRoleType.Creator },
            { Name: "SessionLog", URL: "Sessions/Log.aspx", RequiredRole: Panopto.Data.AclRoleType.Creator }
        ]
    },
    CreateFolderLinks:
    {
        title: "CreateFolderDisplayName",
        modalClass: "createFolder",
        baseUrl: Panopto.appRoot + "/Pages/Folders/",
        pages:
        [
            { Name: "CreateFolder", URL: "Create.aspx" }
        ]
    },
    FolderLinks:
    {
        title: "FolderSettings",
        modalClass: "folderSettings",
        itemClass: "folder",
        baseUrl: Panopto.appRoot + "/Pages/",
        pages:
        [
            { Name: "FolderInfo", URL: "Folders/Info.aspx" },
            { Name: "FolderShare", URL: "Share/Default.aspx", HideOnMaster: true },
            { Name: "FolderSettings", URL: "Folders/Settings.aspx" }
        ]
    },
    CreateUserLinks:
    {
        title: "CreateUserDisplayName",
        modalClass: "createUser",
        baseUrl: Panopto.appRoot + "/Pages/Admin/Users/",
        pages:
        [
            { Name: "CreateUser", URL: "Create.aspx" },
            { Name: "BatchCreateUsers", URL: "BatchCreate.aspx" }
        ]
    },
    UserLinks:
    {
        title: "UserSettings",
        modalClass: "userSettings",
        itemClass: "user",
        baseUrl: Panopto.appRoot + "/Pages/Admin/Users/",
        pages:
        [
            { Name: "UserInfo", URL: "Info.aspx" },
            { Name: "UserPassword", URL: "Password.aspx" },
            { Name: "UserRoles", URL: "Roles.aspx", RequiredRole: Panopto.Data.AclRoleType.Admin },
            { Name: "UserPreset", URL: "Preset.aspx", RequiredRole: Panopto.Data.AclRoleType.Admin }
        ]
    },
    RemoteRecorderLinks:
    {
        title: "RemoteRecorderSettings",
        modalClass: "remoteRecorderSettings",
        itemClass: "remoteRecorder",
        baseUrl: Panopto.appRoot + "/Pages/Admin/RemoteRecorders/",
        pages:
        [
            { Name: "RemoteRecorderInfo", URL: "Info.aspx" },
            { Name: "RemoteRecorderPreview", URL: "Preview.aspx" },
            { Name: "RemoteRecorderSchedule", URL: "Schedule.aspx" }
        ]
    },
    StatsLinks:
    {
        title: "StatsDisplayName",
        modalClass: "statsModal",
        baseUrl: Panopto.appRoot + "/Pages/Stats/",
        pages:
        [
            { Name: "Stats", URL: "Default.aspx" }
        ]
    }
};

// Searches the specified set for the specified page and returns whether or not it was found.
Panopto.ModalPopup.isInSet = function (setName, pageName)
{
    // Filter the pages array down to the items that match the current page name (0 or 1 in practice).
    var matches = $.grep(Panopto.ModalPopup.pageSets[setName].pages, function (item)
    {
        return item.Name == pageName;
    });

    // Convert to bool.
    return !!matches.length;
};

// Localize names for modal groupings.
Panopto.ModalPopup.getPageSetDisplayName = function (pageSet)
{
    return Panopto.LocalResources.ModalPopup[pageSet.title];
};

// Show async load indicator in modal header
Panopto.ModalPopup.showLoadingIndicator = function (show)
{
    if (show || (show == null))
    {
        $(".updating-settings").show();
    }
    else
    {
        $(".updating-settings").hide();
    }
};

// Register the class with MicrosoftAjax once defined.
Panopto.ModalPopup.registerClass("Panopto.ModalPopup");


/*
*  Local resources.  (To be filled in as needed)
*
*  BUGBUG: Migrate to resource files for ship.
*/

Type.registerNamespace("Panopto.LocalResources");

Panopto.LocalResources.ModalPopup = function ()
{
    /// <summary>
    ///     Temporary class to hold localization strings in development.
    /// </summary>
    /// <field name="CreateSessionDisplayName" />

    /// <field name="EditSessionDisplayName" />

    /// <field name="SessionSettings" />
    /// <field name="SessionInfoDisplayName" />
    /// <field name="SessionOutputsDisplayName" />
    /// <field name="SessionContentsDisplayName" />
    /// <field name="SessionLogDisplayName" />
    /// <field name="SessionManageDisplayName" />
    /// <field name="SessionShareDisplayName" />
    
    /// <field name="CreateFolderDisplayName" />
    
    /// <field name="FolderSettings" />
    /// <field name="FolderInfoDisplayName" />
    /// <field name="FolderSettingsDisplayName" />
    /// <field name="FolderShareDisplayName" />
    
    /// <field name="CreateUserDisplayName" />
    /// <field name="BatchCreateUsersDisplayName" />

    /// <field name="UserSettings" />
    /// <field name="UserInfoDisplayName" />
    /// <field name="UserPasswordDisplayName" />
    /// <field name="UserRolesDisplayName" />
    /// <field name="UserPresetDisplayName" />
    
    /// <field name="RemoteRecorderSettings" />
    /// <field name="RemoteRecorderInfoDisplayName" />
    /// <field name="RemoteRecorderPreviewDisplayName" />
    /// <field name="RemoteRecorderScheduleDisplayName" />

    /// <field name="StatsDisplayName" />
}
// e.g. Panopto.LocalResources.ModalPopup.ResourceName = "Resource String";
// When adding new, also add <field...> declaration above.
Panopto.LocalResources.ModalPopup.CreateSessionDisplayName = "Create Session";

Panopto.LocalResources.ModalPopup.EditSession = "Edit Session";

Panopto.LocalResources.ModalPopup.SessionSettings = "Session Settings";
Panopto.LocalResources.ModalPopup.SessionInfoDisplayName = "Overview";
Panopto.LocalResources.ModalPopup.SessionOutputsDisplayName = "Outputs";
Panopto.LocalResources.ModalPopup.SessionContentsDisplayName = "Streams";
Panopto.LocalResources.ModalPopup.SessionLogDisplayName = "Log";
Panopto.LocalResources.ModalPopup.SessionManageDisplayName = "Manage";
Panopto.LocalResources.ModalPopup.SessionShareDisplayName = "Share";

Panopto.LocalResources.ModalPopup.CreateFolderDisplayName = "Create Folder";

Panopto.LocalResources.ModalPopup.FolderSettings = "Folder Settings";
Panopto.LocalResources.ModalPopup.FolderInfoDisplayName = "Info";
Panopto.LocalResources.ModalPopup.FolderSettingsDisplayName = "Settings";
Panopto.LocalResources.ModalPopup.FolderShareDisplayName = "Share";

Panopto.LocalResources.ModalPopup.CreateUserDisplayName = "Create User";
Panopto.LocalResources.ModalPopup.BatchCreateUsersDisplayName = "Batch Create";

Panopto.LocalResources.ModalPopup.UserSettings = "User Settings";
Panopto.LocalResources.ModalPopup.UserInfoDisplayName = "Info";
Panopto.LocalResources.ModalPopup.UserPasswordDisplayName = "Password";
Panopto.LocalResources.ModalPopup.UserRolesDisplayName = "Roles";
Panopto.LocalResources.ModalPopup.UserPresetDisplayName = "Preset";

Panopto.LocalResources.ModalPopup.RemoteRecorderSettings = "Remote Recorder Settings";
Panopto.LocalResources.ModalPopup.RemoteRecorderInfoDisplayName = "Info";
Panopto.LocalResources.ModalPopup.RemoteRecorderPreviewDisplayName = "Preview";
Panopto.LocalResources.ModalPopup.RemoteRecorderScheduleDisplayName = "Schedule";

Panopto.LocalResources.ModalPopup.StatsDisplayName = "Viewing Statistics";

// Registering as enum hides class cruft in Intellisense.
Panopto.LocalResources.ModalPopup.registerEnum("Panopto.LocalResources.ModalPopup");

