/// <reference path="Mediasite.Core.js" />
/// <reference path="../ScriptReference/jquery-1.7.1-vsdoc.js" />

/// <summary>
/// GUI for accessing Mediasite $elements.logging
/// 
/// <pre>javascript:$.getScript('./Javascript/Scripts/Mediasite.LogViewer.js', function() { Mediasite.LogViewer.Load(); });</pre>
/// </summary>

if (!Mediasite) Mediasite = {};
Mediasite.namespace("LogViewer");

(function (window, $, undefined) {
    var module = window.Mediasite.LogViewer;
    var containerId = "MediasiteLogViewer";
    var localStorageKey = containerId;
    var logging = Mediasite.Logging;
    var loaded = false;
 
    module.Load = function () {
        /// <summary>Get a reference to the $elements.log viewer $elements.container (and instantiate it if necessary)</summary>
        /// <returns type="jQuery" />

        if (!($elements.container instanceof $ && $elements.container.length)) {
            createViewer();
            attachToLogging();
        }
        $elements.toggleButton.add($elements.container).fadeIn();
        module.Update();

        loaded = true;

        if (Mediasite.Player.Support.localstorage) {
            localStorage.setItem(localStorageKey, +new Date);
        }

        return true;
    };

    module.Update = function() {
        updateLog();
    };

    module.Destroy = function () {
        detachFromLogging();
        logNames = null;
        
        $elements.toggleButton.add($elements.container).fadeOut(250, function() {
            for (var e in $elements) {
                if ($elements[e]) {
                    $elements[e].remove();
                    $elements[e] = null;
                }
            }
        });

        loaded = false;
        if (Mediasite.Player.Support.localstorage) {
            localStorage.removeItem(localStorageKey);
        }
    };

    module.Loaded = function() { return loaded; }

    var $elements = {
        toggleButton: null,
        container: null,
        closeButton: null,
        logContainer: null,
        log: null,
        tools: null,
        selectFilterLog: null
    };
    var toggleButtonIdSuffix = 'Toggle';
    var toolsIdSuffix = 'Tools';
    var closeButtonIdSuffix = 'Close';
    
    var filterLevel = logging.LogLevel.MinLevel;
    var filterLog = "";

    var positionHorizontalElementIdSuffix = 'PositionHorizontal';
    var positionVerticalElementIdSuffix = 'PositionVertical';

    var positionsVertical = {
        top: 'Top',
        bottom: 'Bottom'
    };
    var positionsHorizontal = {
        left: 'Left',
        right: 'Right'
    };

    var positionCurrent = {
        horizontal: positionsHorizontal.right,
        vertical: positionsVertical.top
    };

    function createViewer() {
        // #region Container
        $elements.container = $('<div></div>').appendTo('body')
            .attr('id', containerId);

        // #endregion

        // #region Toggle button
        $elements.toggleButton = $('<a href="javascript:void(0)" data-toggle-text="show log">hide log</a>')
            .attr('id', containerId + '_' + toggleButtonIdSuffix)
            .appendTo('body');

          $elements.toggleButton.click(function (e) {
            var text = $elements.toggleButton.text();
            $elements.toggleButton.text($elements.toggleButton.data('toggle-text'));
            $elements.toggleButton.data('toggle-text', text);

            $elements.container.toggle();
        });
        // #endregion

        //  #region Close button
        $elements.closeButton = $('<a href="javascript:void(0)">X</a>')
            .attr('id', containerId + '_' + closeButtonIdSuffix)
            .appendTo($elements.container);

        $elements.closeButton.click(function (e) {
            module.Destroy();
        });
        // #endregion

        // Tools
        $elements.tools = $('<div></div>').attr('id', containerId + '_' + toolsIdSuffix).appendTo($elements.container);

        // #region Filter tools

        $elements.filterTools = $('<fieldset></fieldset>').appendTo($elements.tools);
        $('<legend></legend>').appendTo($elements.filterTools)
            .text('Filtering');

        // #region Filter level selector
        $elements.selectFilterLevel = $('<select></select>').appendTo($elements.filterTools);
        $('<option></option>').appendTo($elements.selectFilterLevel)
            .val("")
            .text('Minimum log level');
        
        // Populate options
        var levels = logging.LogLevel.Names;
        for (var level in levels) {
            var levelName = levels[level];
            var $level = $('<option></option>').appendTo($elements.selectFilterLevel)
                .text(levelName).val(level);
            if (level == filterLevel) $level.attr('selected', true);
        }

        // Add onChange handler
        $elements.selectFilterLevel.change(function(e) {
            filterLevel = $elements.selectFilterLevel.val();
            module.Update();
        });
        // #endregion

        // #region Log selector
        $elements.selectFilterLog = $('<select></select>').appendTo($elements.filterTools);
        $('<option></option>').appendTo($elements.selectFilterLog)
            .val("")
            .text('All logs');
        
        // Populate options
        var logNames = logging.LogNames();
        for (var ln in logNames) {
            var logName = logNames[ln];
            addFilterableLog(logName);
        }

        $elements.selectFilterLog.change(function(e) {
            filterLog = $elements.selectFilterLog.val();
            module.Update();
        });
        
        // #endregion filter tools

        // #region Position tools
        $elements.positionTools = $('<fieldset></fieldset>').appendTo($elements.tools);
        $('<legend></legend>').appendTo($elements.positionTools)
            .text('Position')

        // Vertical position
        $elements.positionVertical = $('<select></select>').appendTo($elements.positionTools)
            .attr('id', containerId + '_' + positionVerticalElementIdSuffix)
            .change(function(e) { 
                updatePosition($elements.positionVertical.val(), null);
            });

        
        $('<option></option>').appendTo($elements.positionVertical)
            .val('Top')
            .text('Vertical');

        for (var pv in positionsVertical) {
            var $pvOption = $('<option></option>').appendTo($elements.positionVertical)
                .text(positionsVertical[pv]);
            if (positionsVertical[pv] == positionCurrent.vertical) $pvOption.attr('selected', true);
        }

        // Horizontal position
        $elements.positionHorizontal = $('<select></select>').appendTo($elements.positionTools)
            .attr('id', containerId + '_' + positionHorizontalElementIdSuffix)
            .change(function(e) { 
                updatePosition(null, $elements.positionHorizontal.val());
            });
        
        $('<option></option>').appendTo($elements.positionHorizontal)
            .val('Right')
            .text('Horizontal');

        for (var ph in positionsHorizontal) {
            var $phOption = $('<option></option>').appendTo($elements.positionHorizontal)
                .text(positionsHorizontal[ph]);
            if (positionsHorizontal[ph] == positionCurrent.horizontal) $phOption.attr('selected', true);
        }
        
        // #endregion position tools

        // #region Log output
        $elements.logContainer = $('<table><thead></thead><tbody></tbody></table>').appendTo($elements.container);
        $elements.header = $('<tr></tr>').appendTo('thead', $elements.logContainer);
        $('<th></th>').text('Message').attr('id', containerId + '_MessageItem').appendTo($elements.header);
        $('<th></th>').text('Info').attr('id', containerId + '_InfoItem').appendTo($elements.header);
        

        $elements.log = $('tbody', $elements.logContainer);
        
        // #endregion

        // #region Stylesheet
        var fontSize = '12px';
        var stylesheet = {};
        
        stylesheet['#' + containerId + '_' + toggleButtonIdSuffix] = {
            position: 'absolute',
            'z-index': 999999,
            top: '2em',
            right: '4em',
            border: '.1em white solid',
            '-moz-border-radius': '.5em',
            'border-radius': '.5em',
            background: 'black',
            padding: '.5em',
            'font-weight': 'bold',
            'font-size': fontSize,
            color: 'white',
            'text-decoration': 'none'
        };

        stylesheet['#' + containerId + '_' + toggleButtonIdSuffix + '.' + containerId + '_TopRight'] = {
            top: '2em',
            right: '4em',
            bottom: 'auto',
            left: 'auto'
        };

        stylesheet['#' + containerId + '_' + toggleButtonIdSuffix + '.' + containerId + '_BottomRight'] = {
            top: 'auto',
            right: '4em',
            bottom: '2em',
            left: 'auto'
        };

        stylesheet['#' + containerId + '_' + toggleButtonIdSuffix + '.' + containerId + '_BottomLeft'] = {
            top: 'auto',
            right: 'auto',
            bottom: '2em',
            left: '4em'
        };

        stylesheet['#' + containerId + '_' + toggleButtonIdSuffix + '.' + containerId + '_TopLeft'] = {
            top: '2em',
            right: 'auto',
            bottom: 'auto',
            left: '4em'
        };

         stylesheet['#' + containerId + '_' + closeButtonIdSuffix] = {
                position: 'absolute',
                'z-index': 999999,
                top: '.2em',
                right: '.2em',
                border: '.1em white solid',
                '-moz-border-radius': '.5em',
                'border-radius': '.5em',
                background: 'black',
                padding: '.5em',
                'font-weight': 'bold',
                'font-size': fontSize,
                color: 'white',
                'text-decoration': 'none'
            };

            stylesheet['#' + containerId + '.' + containerId + '_TopRight #' + containerId + '_' + closeButtonIdSuffix] = {
                top: '.2em',
                right: '.2em',
                bottom: 'auto',
                left: 'auto'
            };

            stylesheet['#' + containerId + '.' + containerId + '_BottomRight #' + containerId + '_' + closeButtonIdSuffix] = {
                top: 'auto',
                right: '.2em',
                bottom: '.2em',
                left: 'auto'
            };

            stylesheet['#' + containerId + '.' + containerId + '_BottomLeft' + '  #' + containerId + '_' + closeButtonIdSuffix] = {
                top: 'auto',
                right: 'auto',
                bottom: '.2em',
                left: '.2em'
            };

            stylesheet['#' + containerId + '.' + containerId + '_TopLeft #' + containerId + '_' + closeButtonIdSuffix] = {
                top: '.2em',
                right: 'auto',
                bottom: 'auto',
                left: '.2em'
            };

        stylesheet['#' + containerId] = {
            display: 'none',
            position: 'absolute',
            top: '1em',
            right: '1em',
            'z-index': 999998,
            'font-size': fontSize,
            'box-sizing': 'border-box',
            width: '50%',
            height: '50%',
            border: '.2em gray solid',
            '-moz-border-radius': '.5em',
            'border-radius': '.5em',
            padding: '1em',
            overflow: 'auto',
            background: 'black; background: rgba(0, 0, 0, .6)',
            color: 'rgb(255,255,255)'
        };

        stylesheet['#' + containerId + '.' + containerId + '_TopRight'] = {
            top: '1em',
            right: '1em',
            bottom: 'auto',
            left: 'auto'
        };

        stylesheet['#' + containerId + '.' + containerId + '_BottomRight'] = {
            top: 'auto',
            right: '1em',
            bottom: '1em',
            left: 'auto'
        };

        stylesheet['#' + containerId + '.' + containerId + '_BottomLeft'] = {
            top: 'auto',
            right: 'auto',
            bottom: '1em',
            left: '1em'
        };

        stylesheet['#' + containerId + '.' + containerId + '_TopLeft'] = {
            top: '1em',
            right: 'auto',
            bottom: 'auto',
            left: '1em'
        };
        
        stylesheet['#' + containerId + ' table'] = {
            clear: 'both',
            'table-layout': 'fixed'            
        };

        stylesheet['#' + containerId + ' table th'] = {
            'border-bottom': '1px gray solid',
            'padding': '.2em .5em',
            'text-align': 'left',
            'font-weight': 'bold'
        };

        stylesheet['#' + containerId + ' table th#' + containerId + '_MessageItem'] = {
            width: '65%'
        };

        stylesheet['#' + containerId + ' table th#' + containerId + '_InfoItem'] = {
            width: '30%'
        }

        stylesheet['#' + containerId + ' table td'] = {
            'border-top': '1px gray solid',
            'padding': '.2em .5em',
            'text-align': 'left',
            'font-weight': 'normal'
        };

        stylesheet['#' + containerId + ' table tbody tr:first-child td'] = {
            'border-top': 'none'
        };

         stylesheet['#' + containerId + ' #' + containerId + '_' + toolsIdSuffix] = {
            padding: '1em 1em 2em'
        };

        stylesheet['#' + containerId + '.' + containerId + '_BottomLeft #' + containerId + '_' + toolsIdSuffix] = {
            'padding-left': '2em'
        };

        stylesheet['#' + containerId + '.' + containerId + '_BottomRight #' + containerId + '_' + toolsIdSuffix] = {
            'padding-left': '2em'
        };


        stylesheet['#' + containerId + ' div#' + containerId + '_' + toolsIdSuffix + ' fieldset'] = {        
            'float': 'left',
            'width': '30%'
        };


        stylesheet['#' + containerId + ' div#' + containerId + '_' + toolsIdSuffix + ' legend'] = {        
            display: 'block',
            'text-align': 'center',
            'font-size': '1.2em',
            'font-weight': 'bold',
            'padding': '0 0 0.5em 0'
        };
        
        stylesheet['#' + containerId + ' div#' + containerId + '_' + toolsIdSuffix + ' button'] = {
            display: 'block', 
            'margin-bottom': '1em',
            'box-sizing': 'border-box',
            width: '90%',
            border: '1px white solid',
            '-moz-border-radius': '.5em',
            'border-radius': '.5em',
            background: 'black',
            padding: '.5em',
            color: 'white'
        };

        stylesheet['#' + containerId + ' div#' + containerId + '_' + toolsIdSuffix + ' select'] = {
            display: 'block',
            width: '90%'
        }

        createStylesheet(stylesheet);
        // #endregion
    }

    function createStylesheet(stylesheet) {
        if (document.createStyleSheet) {
            var stylesheetElement = document.createStyleSheet();
            for (var selector in stylesheet) {
                var properties = getStylesheetProperties(stylesheet, selector);
                stylesheetElement.addRule(selector, properties);
            }
        } else {
            var stylesheetText = [];
            for (var selector in stylesheet) {
                var propertiesText = [];
                var properties = getStylesheetProperties(stylesheet, selector);
                
                stylesheetText.push(selector);
                stylesheetText.push('{');
                stylesheetText.push(properties);
                stylesheetText.push('}');
            }

            stylesheetText = stylesheetText.join('\n');
            $('<style type="text/css"></style>').text(stylesheetText).appendTo('html > head');
        }
    }

    function getStylesheetProperties(stylesheet, selector) {
        var properties = stylesheet[selector];
        var propertiesText = [];
        for (var property in properties) {
            var value = properties[property];
            propertiesText.push(property);
            propertiesText.push(':')
            propertiesText.push(value);
            propertiesText.push(';');
        }

        propertiesText = propertiesText.join('');

        return propertiesText;
    }

    function attachToLogging() {
        logging.AddOutput(handleLogItem);
    }

    function detachFromLogging() {
        logging.RemoveOutput(handleLogItem);
    }

    function updateLog() {
        $elements.log.empty();

        var logItems = logging.Tail(0, filterLevel, filterLog);
        for (var li in logItems) {
            if (!logItems.hasOwnProperty(li)) continue;
            var logItem = logItems[li];
            handleLogItem(logItem);
        }
    }

    var logNames = {};
    function addFilterableLog(logName) {
        logNames = logNames || {};
        if (logNames[logName]) return;

        $elements.logName = $('<option></option>').appendTo($elements.selectFilterLog)
                .text(logName).val(logName);

        logNames[logName] = true;
    }

    function handleLogItem(logItem) {
        addFilterableLog(logItem.LogName);
        if (filterLevel && logItem.LogLevel < filterLevel) return;
        if (filterLog && logItem.LogName != filterLog) return;

        var $cont = $elements.container;
        var cont = $elements.container.get(0);
        var shouldScrollToBottom = false;
        try {
            shouldScrollToBottom = Math.abs(cont.scrollHeight - cont.scrollTop) < $elements.container.height() + 100;
        } catch (err) {}

        $elements.logRow = $('<tr></tr>').appendTo($elements.log);
        
        var message = prepareMessage(logItem.Message);
        var info = [
            logItem.FormattedTimestamp,
            logging.LogLevel.GetDisplayName(logItem.LogLevel),
            logItem.LogName
            ].join(', ');

        $('<td></td>').html(message).appendTo($elements.logRow);
        $('<td></td>').text(info).appendTo($elements.logRow);

        if (shouldScrollToBottom) {
            try {
                cont.scrollTop = cont.scrollHeight;
            } catch (err) {}
        }
    }
    
    var newlineRE = /\n/g;
    var spaceRE = /\s{2}/g;
    function prepareMessage(text) {
        text = text.replace(newlineRE, '<br>');
        text = text.replace(spaceRE, '&nbsp;');

        return text;
    }

    function updatePosition(newPositionVertical, newPositionHorizontal) {
        if (!(newPositionHorizontal || newPositionVertical)) return;
        
        var oldClass = getPositionClass();
        $elements.container.removeClass(oldClass);
        $elements.toggleButton.removeClass(oldClass);

        // Sanitize positionCurrent
        positionCurrent.vertical = newPositionVertical || positionCurrent.vertical || positionsVertical.top;
        positionCurrent.horizontal = newPositionHorizontal|| positionCurrent.horizontal|| positionsHorizontal.right;

        var newClass = getPositionClass();
        $elements.container.addClass(newClass);
        $elements.toggleButton.addClass(newClass);
    }

    function getPositionClass() {
        var positionClass = [
            containerId, 
            '_',
            positionCurrent.vertical,
            positionCurrent.horizontal
            ].join('');
        return positionClass;
    }
    

    $(function() {
        if (Mediasite.Player.Support.localstorage) {   
            var lastShown = localStorage.getItem(localStorageKey);
            if (!lastShown) return;
            lastShown = new Date(parseInt(lastShown));
            if (lastShown > (new Date() - (1000 * 60 * 30))) {
                setTimeout(module.Load, 2000); 
            }
        }
    });


})(this, jQuery);
