// This module tracks what is currently focused and what the last element was that had the focus.  It also exposes
// a method that figures out what element should receive focus after a panel is closed.  It does this by determining
// if the current or last focused element is contained within the closing panel.  This information is passed in via a 
// JSON object when the module is instanciated.  
// Generally, if the focused element
// is not a child of the panel, we can say that the user intentionally navigated to that element and we should not
// return focus to the panel toggle button.  If the user was navigating within the elements of the closing panel,
// we return focus to the panels toggle button.
// Special attention is paid to the close button - we want to know if the user clicked or pressed Enter on the close
// button.  If it was an Enter key, we return focus to the closing panels open button.  Otherwise, check to see if
// the last focused item is in the closing panel. If so, return the panels open button.  Else, return the last
// focused element.



Mediasite.Player.PanelFocusResetter = function (panelButtonsAndElements) {

    var self = this;
    var _focusedElement;
    var _lastFocusedElement;
    var _panelButtonsAndElements = {};

    $("body").on('focusin', focusedElementChanged);
    _panelButtonsAndElements = panelButtonsAndElements;

    // track the focused element and the last focused element - setTimeout is a hack that allows document.activeElement to be reliable
    function focusedElementChanged(e) {
        setTimeout(function () {
            if ($(document.activeElement) != undefined) {
                self.SetFocusedElement($(document.activeElement));
            }
        }, 1);
    }

    function focusedElementBelongsToPanel(panelButton) {
        var panelElement = getPanelElementPerPanelButton(panelButton);
        return ($(panelElement).find(_focusedElement).length);
    }

    function lastFocusedElementBelongsToPanel(panelButton) {
        var panelElement = getPanelElementPerPanelButton(panelButton);
        return ($(panelElement).find(_lastFocusedElement).length);
    }

    function getPanelCloseButtonPerPanelButton(panelButton) {
        for (var i = 0; i < _panelButtonsAndElements.length; i++) {
            if (panelButton.is(_panelButtonsAndElements[i].panelButton)) {
                return _panelButtonsAndElements[i].panelCloseButton;
            }
        }
        return null;
    }

    function focusedElementIsPanelCloseButton(panelButton) {
        var panelCloseButton = getPanelCloseButtonPerPanelButton(panelButton);

        if (_focusedElement)
            return _focusedElement.is(panelCloseButton);
        else
            return false;
    }

    function getActivePanelButtonAndElements(panelButton) {
        for (var i = 0; i < _panelButtonsAndElements.length; i++) {
            if (panelButton.is(_panelButtonsAndElements[i].panelButton)) {
                return _panelButtonsAndElements[i];
            }
        }
        return null;
    }

    function getPanelElementPerPanelButton(panelButton) {
        for (var i = 0; i < _panelButtonsAndElements.length; i++) {
            if (panelButton.is(_panelButtonsAndElements[i].panelButton)) {
                return _panelButtonsAndElements[i].panelElement;
            }
        }
        return null;
    }

    function getPanelButtonPerPanelElement(panelElement) {
        var panelButton = null
        for (var i = 0; i < _panelButtonsAndElements.length; i++) {
            if (panelElement.is(_panelButtonsAndElements[i].panelElement)) {
                panelButton = _panelButtonsAndElements[i].panelButton;
                break;
            }
        }
        return panelButton;
    }

    function getPanelElementPerFocusedElement() {
        var panelElement = null;
        for (var i = 0; i < _panelButtonsAndElements.length; i++) {
            if (_panelButtonsAndElements[i].panelElement.find(_focusedElement).length) {
                panelElement = _panelButtonsAndElements[i].panelElement;
                break;
            }
        }
        return panelElement;
    }

    ///////////////////////////////////////////////////////////////////
    // Primary Function - user clicks 'esc' to close all panels
    ///////////////////////////////////////////////////////////////////

    function getElementToResetFocusToAfterAllClosed() {

        if (document.activeElement == null || document.activeElement.tagName.toUpperCase() == "BODY")
            return panelButton;

        var panelElement = getPanelElementPerFocusedElement();

        if (panelElement) {
            var panelButton = getPanelButtonPerPanelElement(panelElement);
            return panelButton;
        } else
            return _focusedElement;
    }

    ///////////////////////////////////////////////////////////////////
    // Primary Function - user clicks the close button close one panel
    // and one is still open
    ///////////////////////////////////////////////////////////////////

    function getElementToResetFocusToAfterOneClosedSomeStillOpen(panelButton, clickType) {

        if (document.activeElement == null || document.activeElement.tagName.toUpperCase() == "BODY")
            return panelButton;

        // user 'clicked' the Close button - need to see if it was a click or the Enter key
        if (focusedElementIsPanelCloseButton(panelButton)) {

            if (clickType == Mediasite.Player.PanelFocusResetter.ClickType.MouseClick) {
                if (lastFocusedElementBelongsToPanel(panelButton))
                    return panelButton;
                else
                    return _lastFocusedElement;
            } else {
                return panelButton;
            }
        } else {

            // Esc was pressed - just see if the focused item was in our
            if (focusedElementBelongsToPanel(panelButton))
                return panelButton;
            else
                return _focusedElement;
        }

    }

    // At this time, getElementToResetFocusToAfterOneClosedSomeStillOpen() is call for both 
    // OneClosedSomeStillOpen and OneClosedNoneStillOpen.  The structure is in place so that we can
    // implement a specific behavior for each of the 'panelClosing' types.

    this.GetElementToResetFocusTo = function (panelClosingType, panelButton, clickType) {

        if (clickType == null)
            clickType = Mediasite.Player.PanelFocusResetter.ClickType.MouseClick;

        if (panelClosingType == Mediasite.Player.PanelFocusResetter.PanelClosingType.AllClosed) {

            return getElementToResetFocusToAfterAllClosed();

        } else if (panelClosingType == Mediasite.Player.PanelFocusResetter.PanelClosingType.OneClosedSomeStillOpen) {

            return getElementToResetFocusToAfterOneClosedSomeStillOpen(panelButton, clickType);

        } else if (panelClosingType == Mediasite.Player.PanelFocusResetter.PanelClosingType.OneClosedNoneStillOpen) {

            return getElementToResetFocusToAfterOneClosedSomeStillOpen(panelButton, clickType);

        }
    }

    this.SetFocusedElement = function (element) {
        var jQueryElement = $(element);

        _lastFocusedElement = _focusedElement;
        _focusedElement = jQueryElement;
    }

    this.GetFocusedElement = function () {
        return _focusedElement;
    }

    this.FocusedElementIs = function (selector) {
        return _focusedElement.is($(selector));
    }
}


Mediasite.Player.PanelFocusResetter.PanelClosingType = {
    AllClosed: "AllClosed",
    OneClosedSomeStillOpen: "OneClosedSomeStillOpen",
    OneClosedNoneStillOpen: "OneClosedNoneStillOpen"
};

Mediasite.Player.PanelFocusResetter.ClickType = {
    MouseClick: "MouseClick",
    KeyPress: "KeyPress"
};
