// ----------------------------------------------------------------------
// VARS
// ----------------------------------------------------------------------

// current winbox instances
var aWinBoxes = {};

// default frame border color for winboxes
var WINBOX_data = false;
var WINBOX_lsvariable = "winbox_data";
var WINBOX_defaults = {
    background: "#456",
    border: 5,
    class: ["no-min", "no-max", "no-full", "ciwinboxinfos"],

    // viewport
    top: 70,
    right: 20,
    bottom: 20,
    left: 20

};


/**
 * get data of all winboxes - or of a single winbox only - from localstorage
 * @param {string} sId  optional: id of a winbox
 * @returns 
 */
function wb_getdata(sId) {
    WINBOX_data = WINBOX_data 
        ? WINBOX_data 
        : (localStorage.getItem(WINBOX_lsvariable) 
            ? JSON.parse(localStorage.getItem(WINBOX_lsvariable)) 
            : {}
        );
    return sId
        ? (WINBOX_data[sId] ? WINBOX_data[sId] : {})
        : WINBOX_data;
}
/**
 * get data of all winboxes - or of a single winbox only - from localstorage
 * @param {string} sId  optional: id of a winbox
 * @returns 
 */
function wb_getdefaults(sId, aOverrides) {
    var _aReturn = Object.assign({}, WINBOX_defaults);
    for (var key in aOverrides) {
        _aReturn[key] = aOverrides[key];
    }
    var _aData = wb_getdata(sId);
    for (var key in _aData) {
        _aReturn[key] = _aData[key];
    }
    if (_aReturn['x']<_aReturn['left']){
        _aReturn['x']=_aReturn['left'];
    }
    if (_aReturn['y']<_aReturn['top']){
        _aReturn['y']=_aReturn['top'];
    }
    return _aReturn;
}
/**
 * save data for a given winbox
 * @param {string} sId         id of a winbox
 * @param {array} _aNewvalues  properties to store as key+value
 */
function wb_savedata(sId, _aNewvalues) {
    WINBOX_data = WINBOX_data ? WINBOX_data : wb_getdata();
    if (!WINBOX_data[sId]) {
        WINBOX_data[sId] = {};
    }
    for (var key in _aNewvalues) {
        WINBOX_data[sId][key] = _aNewvalues[key];
    }
    localStorage.setItem(WINBOX_lsvariable, JSON.stringify(WINBOX_data));
}


// ----------------------------------------------------------------------
// FUNCTIONS
// ----------------------------------------------------------------------

/**
 * initialize soft scrolling for links with css class "scroll-link"
 * @see http://css-tricks.com/snippets/jquery/smooth-scrolling/
 * @returns {undefined}
 */
function initSoftscroll() {
    $(function () {
        // $('a[href*=#]:not([href=#])').click(function() {
        $('a.scroll-link').click(function () {
            if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) {
                var target = $(this.hash);
                target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
                if (target.length) {
                    $('html,body').animate({
                        scrollTop: target.offset().top - 70
                    }, 300);
                    return false;
                }
            }
        });
    });
}


/**
 * Shows a modal message by setting the inner HTML of div#divmodalmessage 
 * to the given message, and showing div#divmodal.
 * 
 * @param {string} sMessage - The message to display in the modal
 */
function showModalMessage(sMessage) {
    $('#divmodalmessage').html(sMessage);
    $('#divmodal').show();
}

/**
 * Hide modal message box
 */
function hideModalMessage() {
    $('#divmodal').hide();
    return false;
}

/**
 * show a window displaying the content of a given dom id using Winbox
 * 
 * @param {string} sId     dom id of a div to show
 * @param {string} sTitle  title for the winbox window
 * @returns 
 */
function showIdAsModalMessage(sId, sTitle) {

    if (aWinBoxes[sId]) {
        return true;
    }
    var oWrapper = document.getElementById(sId);
    var aOptions = wb_getdefaults(sId, {
        title: sTitle,
        id: 'winbox-' + sId,

        // position + size
        x: "center",
        y: "center",
        width: 700,
        height: 500,


        // take content from existing div
        // mount: oWrapper
        // mount: document.getElementById(sId).cloneNode(true),
        html: oWrapper.innerHTML,

        onmove:   function (x, y) { wb_savedata(sId, { x: x,     y: y      }); },
        onresize: function (x, y) { wb_savedata(sId, { width: x, height: y }); },
        onclose: function () {
            delete aWinBoxes[sId];
        }
    });
    aWinBoxes[sId] = WinBox(aOptions);

    return false;
}

/**
 * shellcmd plugin ... toggle output window
 * @param {string} sId  id of the wrapper
 * @param {object} oLink              a tag in the navbar with link for toggling window 
 */
function toggleShellWindow(sId, oLink) {
    if (aWinBoxes[sId]) {
        aWinBoxes[sId].close();
    } else {
        var oWrapper = document.getElementById(sId);
        var aOptions = wb_getdefaults(sId, {
            title: oLink.innerText,
            id: 'winbox-' + sId,
            class: ["no-min", "no-max", /* "no-full", "no-resize", "no-move"*/ "ciwinbox"],

            // position + size
            x: "center",
            y: "center",
            width: 10,
            height: 10,

            // take content from existing div
            mount: oWrapper,

            onmove:   function (x, y) { wb_savedata(sId, { x: x,     y: y      }); },
            onresize: function (x, y) { wb_savedata(sId, { width: x, height: y }); },        
            onclose: function () {
                delete aWinBoxes[sId];
                $(oLink).removeClass('active');
            }
        });
        aWinBoxes[sId] = WinBox(aOptions);

        if (oLink) {
            $(oLink).addClass('active');
        }
        if(aOptions['width']==10){
            window.setTimeout("aWinBoxes['" + sId + "'].resize(" + (oWrapper.clientWidth + 25) + ", " + (oWrapper.clientHeight + 150) + ").move('center', 'center')", 10);
        }
    }
}

// ----------------------------------------------------------------------
// general init in each page
// ----------------------------------------------------------------------

$(document).ready(function () {
    initSoftscroll();
});


// ----------------------------------------------------------------------
// action log
// ----------------------------------------------------------------------

/**
 * get filtered action log table
 * @returns {undefined}
 */
function updateActionlog() {
    var sUrlBase = "/webservice/?class=Actionlog&action=getLogs&type=json&args=";

    // columns in output table
    var aTableitems = ["id", "time", "loglevel", "ip", "user", "project", "action", "message"];

    var aArgs = {
        'project': $('#selectproject').val(),
        'from': $('#selectfrom').val(),
        'to': $('#selectto').val(),
        'limit': $('#selectlimit').val(),
    }

    // --- get data

    var sUrl = sUrlBase + '[' + JSON.stringify(aArgs) + ']';
    $.post(sUrl, function (aData) {
        var sHtml = '';

        // --- generate output
        if (aData.length && aData[0]["id"]) {
            for (i = 0; i < aData.length; i++) {
                sHtml += '<tr class="tractionlogs loglevel-' + aData[i]["loglevel"] + ' ' + aData[i]["project"] + '">';
                for (j = 0; j < aTableitems.length; j++) {
                    sHtml += '<td>' + aData[i][aTableitems[j]] + '</td>';
                }
                sHtml += '</tr>';
            }
        }
        drawTimeline(aData);

        if (!sHtml) {
            sHtml = sMsgNolog; // variable is set in actionlog.class.php
        } else {
            sHead = '';
            for (j = 0; j < aTableitems.length; j++) {
                sHead += '<th>' + aTableitems[j] + '</th>';
            }
            sHead = '<thead><tr>' + sHead + '</tr></thead>';
            sHtml = '<table class="table table-condensed">' + sHead + '<tbody>' + sHtml + '</tbody></table>';
        }
        $('#tableLogactions').html(sHtml);
        filterLogTable();
    });

}
/**
 * render timeline with Visjs
 * 
 * @param {array} aData
 * @returns {undefined}
 */
function drawTimeline(aData) {
    var sDataset = '';

    var container = document.getElementById('divTimeline');
    if (!container) {
        return false;
    }
    container.innerHTML = ''; // empty the div

    if (aData.length && aData[0]["id"]) {
        for (i = 0; i < aData.length; i++) {
            // keys are 
            // var aTableitems=["id", "time", "loglevel", "ip", "user", "project", "action", "message"];
            sLabel = aData[i]["project"] + '<br>' + aData[i]["action"];
            sTitle = aData[i]["time"] + '<br>' + aData[i]["loglevel"] + '<br><br>Projekt: ' + aData[i]["project"] + '<br>User: ' + aData[i]["user"] + ' (' + aData[i]["ip"] + ')<br>' + aData[i]["message"];
            sDataset += (sDataset ? ', ' : '')
                + '{"id": ' + i + ', "content": "' + sLabel + '", "start": "' + aData[i]["time"].replace(/\ /, "T") + '", "title": "' + sTitle + '", "group": "' + aData[i]["project"] + '", "className": "loglevel-' + aData[i]["loglevel"] + '"  }';
        }
        aDataset = JSON.parse('[' + sDataset + ']');

        var items = new vis.DataSet(aDataset);

        // Configuration for the Timeline
        var options = {
            // verticalScroll: false,
            clickToUse: true
        };

        // Create a Timeline
        var timeline = new vis.Timeline(container, items, options);
    }
}

/**
* filter table with action logs by filtertext (input field)
*/
function filterLogTable() {
    var sSearch = $("#efilterlogs").val();
    var Regex = new RegExp(sSearch, "i");
    $(".tractionlogs").each(function () {
        sVisible = "none";
        if (Regex.exec(this.innerHTML)) {
            sVisible = "";
        }
        $(this).css("display", sVisible);
    });
    return false;
}

// ----------------------------------------------------------------------
// tables
// ----------------------------------------------------------------------
var localStoreTablefilter = "tblvalue" + location.pathname;


// http://blog.mastykarz.nl/jquery-regex-filter/
jQuery.extend(
    jQuery.expr[':'], {
    regex: function (a, i, m) {
        var r = new RegExp(m[3], 'i');
        return r.test(jQuery(a).text());
    }
}
);

/*
 highlight v4
 Highlights arbitrary terms.
 
 <http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>
 
 MIT license.
 
 Johann Burkard
 <http://johannburkard.de>
 <mailto:jb@eaio.com>
 */

jQuery.fn.highlight = function (pat) {
    function innerHighlight(node, pat) {
        var skip = 0;
        if (node.nodeType == 3) {
            var pos = node.data.toUpperCase().indexOf(pat);
            if (pos >= 0) {
                var spannode = document.createElement('span');
                spannode.className = 'highlight';
                var middlebit = node.splitText(pos);
                var endbit = middlebit.splitText(pat.length);
                var middleclone = middlebit.cloneNode(true);
                spannode.appendChild(middleclone);
                middlebit.parentNode.replaceChild(spannode, middlebit);
                skip = 1;
            }
        }
        else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
            for (var i = 0; i < node.childNodes.length; ++i) {
                i += innerHighlight(node.childNodes[i], pat);
            }
        }
        return skip;
    }
    return this.length && pat && pat.length ? this.each(function () {
        innerHighlight(this, pat.toUpperCase());
    }) : this;
};

jQuery.fn.removeHighlight = function () {
    return this.find("span.highlight").each(function () {
        this.parentNode.firstChild.nodeName;
        with (this.parentNode) {
            replaceChild(this.firstChild, this);
            normalize();
        }
    }).end();
};


/**
 * add a filter form to a table
 * @returns {undefined}
 */
function addFilterToTable() {
    var sValue = localStorage.getItem(localStoreTablefilter) ? localStorage.getItem(localStoreTablefilter) : '';
    var sForm = '<form class="pure-form">\n\
        <fieldset>\n\
            <label for="eFilter">\n\
                <i class="fa fa-filter"></i> Tabelle filtern\n\
            </label>\n\
            <input type="text" id="eFilter" size="40" name="q" placeholder="Suchbegriff..." value="'+ sValue + '" onkeypress="filterTable(this);" onkeyup="filterTable(this);" onchange="filterTable(this);">\n\
            <button class="pure-button" onclick="$(\'#eFilter\').val(\'\'); filterTable(); return false;"><i class="fa fa-times"></i> </button>\n\
            <span id="filterinfo"></span>\n\
        </fieldset>\n\
        </form><div style="clear: both;"></div>';
    $(sForm).insertBefore($("table").first());
}


/**
 * callback ... filter the table
 * use addFilterToTable() before.
 * @returns {undefined}
 */
function filterTable() {
    var filter = $('#eFilter').val();
    localStorage.setItem(localStoreTablefilter, filter);
    $("table").removeHighlight();
    if (filter) {
        $("tr:regex('" + filter + "')").show();
        $("tr:not(:regex('" + filter + "'))").hide();
        $("tr").first().show();

        $("td").highlight(filter);
    } else {
        $("td").removeHighlight();
        $('tr').show();
    }

    var sInfo = '';
    var iVisible = -1; // 1 abziehen wg. tr der ersten Zeile
    $("tr").each(function () {
        if ($(this).css('display') != 'none') {
            iVisible++;
        }
    });

    sInfo = (iVisible == ($("tr").length - 1))
        ? "ges.: <strong>" + ($("tr").length - 1) + "</strong> Eintr&auml;ge"
        : "<strong>" + iVisible + "</strong> von " + ($("tr").length - 1) + " Eintr&auml;gen"
        ;
    $('#filterinfo').html(sInfo);

}


// ----------------------------------------------------------------------
// API secret
// ----------------------------------------------------------------------
function generateSecret(length) {

    var result = '';
    var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var charactersLength = characters.length;
    for (var i = 0; i < length; i++) {
        result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
}

// ----------------------------------------------------------------------