/**
 * Copyright JS Foundation and other contributors, http://js.foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/
RED.sidebar.info = (function() {

    var content;
    var panels;
    var infoSection;

    var propertiesPanelContent;
    var propertiesPanelHeader;
    var propertiesPanelHeaderIcon;
    var propertiesPanelHeaderLabel;
    var propertiesPanelHeaderReveal;
    var propertiesPanelHeaderHelp;
    var propertiesPanelHeaderCopyLink;

    var selectedObject;

    var tipContainer;
    var tipBox;

    // TODO: remove this
    var expandedSections = {
        "property": false
    };

    function resizeStack() {
        if (panels) {
            var h = $(content).parent().height() - tipContainer.outerHeight();
            panels.resize(h)
        }
    }
    function init() {

        content = document.createElement("div");
        content.className = "red-ui-sidebar-info"

        RED.actions.add("core:show-info-tab",show);

        var stackContainer = $("<div>",{class:"red-ui-sidebar-info-stack"}).appendTo(content);

        var outlinerPanel = $("<div>").css({
            "overflow": "hidden",
            "height": "calc(70%)"
        }).appendTo(stackContainer);
        var propertiesPanel = $("<div>").css({
            "overflow":"hidden",
            "height":"100%",
            "display": "flex",
            "flex-direction": "column"
        }).appendTo(stackContainer);
        propertiesPanelHeader = $("<div>", {class:"red-ui-palette-header red-ui-info-header"}).css({
            "flex":"0 0 auto"
        }).appendTo(propertiesPanel);

        propertiesPanelHeaderIcon = $("<span>").appendTo(propertiesPanelHeader);
        propertiesPanelHeaderLabel = $("<span>").appendTo(propertiesPanelHeader);

        propertiesPanelHeaderCopyLink = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-link"></button>').css({
            position: 'absolute',
            top: '12px',
            right: '32px'
        }).on("click", function(evt) {
            RED.actions.invoke('core:copy-item-url',selectedObject)
        }).appendTo(propertiesPanelHeader);
        RED.popover.tooltip(propertiesPanelHeaderCopyLink,RED._("sidebar.info.copyItemUrl"));

        propertiesPanelHeaderHelp = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-book"></button>').css({
            position: 'absolute',
            top: '12px',
            right: '56px'
        }).on("click", function(evt) {
            evt.preventDefault();
            evt.stopPropagation();
            if (selectedObject) {
                RED.sidebar.help.show(selectedObject.type);
            }
        }).appendTo(propertiesPanelHeader);
        RED.popover.tooltip(propertiesPanelHeaderHelp,RED._("sidebar.help.showHelp"));

        propertiesPanelHeaderReveal = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-search"></button>').css({
            position: 'absolute',
            top: '12px',
            right: '8px'
        }).on("click", function(evt) {
            evt.preventDefault();
            evt.stopPropagation();
            if (selectedObject) {
                RED.sidebar.info.outliner.reveal(selectedObject);
                RED.view.reveal(selectedObject.id);
            }
        }).appendTo(propertiesPanelHeader);
        RED.popover.tooltip(propertiesPanelHeaderReveal,RED._("sidebar.help.showInOutline"));


        propertiesPanelContent = $("<div>").css({
            "flex":"1 1 auto",
            "overflow-y":"auto",
        }).appendTo(propertiesPanel);


        panels = RED.panels.create({container: stackContainer})
        panels.ratio(0.6);
        RED.sidebar.info.outliner.build().appendTo(outlinerPanel);


        RED.sidebar.addTab({
            id: "info",
            label: RED._("sidebar.info.label"),
            name: RED._("sidebar.info.name"),
            iconClass: "fa fa-info",
            action:"core:show-info-tab",
            content: content,
            pinned: true,
            enableOnEdit: true
        });

        RED.events.on("sidebar:resize", resizeStack);

        $(window).on("resize", resizeStack);
        $(window).on("focus", resizeStack);


        // Tip Box
        tipContainer = $('<div class="red-ui-help-tips"></div>').appendTo(content);
        tipBox = $('<div class="red-ui-help-tip"></div>').appendTo(tipContainer);
        var tipButtons = $('<div class="red-ui-help-tips-buttons"></div>').appendTo(tipContainer);

        var tipRefresh = $('<a href="#" class="red-ui-footer-button"><i class="fa fa-refresh"></a>').appendTo(tipButtons);
        tipRefresh.on("click", function(e) {
            e.preventDefault();
            tips.next();
        })

        var tipClose = $('<a href="#" class="red-ui-footer-button"><i class="fa fa-times"></a>').appendTo(tipButtons);
        tipClose.on("click", function(e) {
            e.preventDefault();
            RED.actions.invoke("core:toggle-show-tips");
            RED.notify(RED._("sidebar.info.showTips"));
        });
        if (tips.enabled()) {
            tips.start();
        } else {
            tips.stop();
        }

    }

    function show() {
        RED.sidebar.show("info");
    }

    // TODO: DRY - projects.js
    function addTargetToExternalLinks(el) {
        $(el).find("a").each(function(el) {
            var href = $(this).attr('href');
            if (/^https?:/.test(href)) {
                $(this).attr('target','_blank');
            }
        });
        return el;
    }

    function refresh(node) {
        if (node === undefined) {
            refreshSelection();
            return;
        }
        $(propertiesPanelContent).empty();

        var propRow;

        var table = $('<table class="red-ui-info-table"></table>').appendTo(propertiesPanelContent);
        var tableBody = $('<tbody>').appendTo(table);

        var subflowNode;
        var subflowUserCount;

        if (node === null) {
            RED.sidebar.info.outliner.select(null);
            propertiesPanelHeaderIcon.empty();
            propertiesPanelHeaderLabel.text("");
            propertiesPanelHeaderReveal.hide();
            propertiesPanelHeaderHelp.hide();
            propertiesPanelHeaderCopyLink.hide();
            return;
        } else if (Array.isArray(node)) {
            // Multiple things selected
            // - hide help and info sections
            RED.sidebar.info.outliner.select(node);

            propertiesPanelHeaderIcon.empty();
            RED.utils.createNodeIcon({type:"_selection_"}).appendTo(propertiesPanelHeaderIcon);
            propertiesPanelHeaderLabel.text(RED._("sidebar.info.selection"));
            propertiesPanelHeaderReveal.hide();
            propertiesPanelHeaderHelp.hide();
            propertiesPanelHeaderCopyLink.hide();
            selectedObject = null;

            var types = {
                nodes:0,
                flows:0,
                subflows:0,
                groups: 0
            }
            node.forEach(function(n) {
                if (n.type === 'tab') {
                    types.flows++;
                    types.nodes += RED.nodes.filterNodes({z:n.id}).length;
                } else if (n.type === 'subflow') {
                    types.subflows++;
                } else if (n.type === 'group') {
                    types.groups++;
                } else {
                    types.nodes++;
                }
            });
            // infoSection.container.hide();
            // - show the count of selected nodes
            propRow = $('<tr class="red-ui-help-info-row"><td>'+RED._("sidebar.info.selection")+"</td><td></td></tr>").appendTo(tableBody);

            var counts = $('<div>').appendTo($(propRow.children()[1]));
            if (types.flows > 0) {
                $('<div>').text(RED._("clipboard.flow",{count:types.flows})).appendTo(counts);
            }
            if (types.subflows > 0) {
                $('<div>').text(RED._("clipboard.subflow",{count:types.subflows})).appendTo(counts);
            }
            if (types.nodes > 0) {
                $('<div>').text(RED._("clipboard.node",{count:types.nodes})).appendTo(counts);
            }
            if (types.groups > 0) {
                $('<div>').text(RED._("clipboard.group",{count:types.groups})).appendTo(counts);
            }
        } else {
            // A single 'thing' selected.

            RED.sidebar.info.outliner.select(node);

            // Check to see if this is a subflow or subflow instance
            var subflowRegex = /^subflow(:(.+))?$/.exec(node.type);
            if (subflowRegex) {
                if (subflowRegex[2]) {
                    subflowNode = RED.nodes.subflow(subflowRegex[2]);
                } else {
                    subflowNode = node;
                }

                var subflowType = "subflow:"+subflowNode.id;
                subflowUserCount = subflowNode.instances.length;
            }

            propertiesPanelHeaderIcon.empty();
            RED.utils.createNodeIcon(node).appendTo(propertiesPanelHeaderIcon);
            var objectLabel = RED.utils.getNodeLabel(node, node.type+": "+node.id)
            var newlineIndex = objectLabel.indexOf("\\n");
            if (newlineIndex > -1) {
                objectLabel = objectLabel.substring(0,newlineIndex)+"...";
            }
            propertiesPanelHeaderLabel.text(objectLabel);
            propertiesPanelHeaderReveal.show();
            selectedObject = node;

            propRow = $('<tr class="red-ui-help-info-row"><td></td><td></td></tr>').appendTo(tableBody);
            var objectType = "node";
            if (node.type === "subflow" || subflowRegex) {
                objectType = "subflow";
            } else if (node.type === "tab") {
                objectType = "flow";
            }else if (node.type === "group") {
                objectType = "group";
            }
            $(propRow.children()[0]).text(RED._("sidebar.info."+objectType))
            RED.utils.createObjectElement(node.id,{sourceId: node.id}).appendTo(propRow.children()[1]);

            if (node.type === "tab" || node.type === "subflow") {
                // If nothing is selected, but we're on a flow or subflow tab.
                propertiesPanelHeaderHelp.hide();
                propertiesPanelHeaderCopyLink.show();

            } else if (node.type === "group") {
                propertiesPanelHeaderHelp.hide();
                propertiesPanelHeaderCopyLink.show();

                propRow = $('<tr class="red-ui-help-info-row"><td>&nbsp;</td><td></td></tr>').appendTo(tableBody);

                var typeCounts = {
                    nodes:0,
                    groups: 0
                }
                var allNodes = RED.group.getNodes(node,true);
                allNodes.forEach(function(n) {
                    if (n.type === "group") {
                        typeCounts.groups++;
                    } else {
                        typeCounts.nodes++
                    }
                });
                var counts = $('<div>').appendTo($(propRow.children()[1]));
                if (typeCounts.nodes > 0) {
                    $('<div>').text(RED._("clipboard.node",{count:typeCounts.nodes})).appendTo(counts);
                }
                if (typeCounts.groups > 0) {
                    $('<div>').text(RED._("clipboard.group",{count:typeCounts.groups})).appendTo(counts);
                }
            } else if (node.type === 'junction') {
                propertiesPanelHeaderHelp.hide();
                propertiesPanelHeaderCopyLink.hide();
            } else {
                propertiesPanelHeaderHelp.show();
                propertiesPanelHeaderCopyLink.show();

                if (!subflowRegex) {
                    propRow = $('<tr class="red-ui-help-info-row"><td>'+RED._("sidebar.info.type")+'</td><td></td></tr>').appendTo(tableBody);
                    $(propRow.children()[1]).text((node.type === "unknown")?node._orig.type:node.type);
                    if (node.type === "unknown") {
                        $('<span style="float: right; font-size: 0.8em"><i class="fa fa-warning"></i></span>').prependTo($(propRow.children()[1]))
                    }
                }

                var count = 0;
                if (!subflowRegex && node.type != "subflow" && node.type != "group") {

                    var blankRow = $('<tr class="red-ui-help-property-expand blank"><td colspan="2"></td></tr>').appendTo(tableBody);

                    var defaults;
                    if (node.type === 'unknown') {
                        defaults = {};
                        Object.keys(node._orig).forEach(function(k) {
                            if (k !== 'type') {
                                defaults[k] = {};
                            }
                        })
                    } else if (node._def) {
                        defaults = node._def.defaults;
                        propRow = $('<tr class="red-ui-help-info-property-row'+(expandedSections.property?"":" hide")+'"><td>'+RED._("sidebar.info.module")+"</td><td></td></tr>").appendTo(tableBody);
                        $(propRow.children()[1]).text(RED.nodes.getType(node.type).set.module);
                        count++;
                    }

                    if (defaults) {
                        for (var n in defaults) {
                            if (n != "name" && n != "info" && defaults.hasOwnProperty(n)) {
                                var val = node[n];
                                var type = typeof val;
                                count++;
                                propRow = $('<tr class="red-ui-help-info-property-row'+(expandedSections.property?"":" hide")+'"><td></td><td></td></tr>').appendTo(tableBody);
                                $(propRow.children()[0]).text(n);
                                if (defaults[n].type && !defaults[n]._type.array) {
                                    var configNode = RED.nodes.node(val);
                                    if (!configNode) {
                                        RED.utils.createObjectElement(undefined).appendTo(propRow.children()[1]);
                                    } else {
                                        var configLabel = RED.utils.getNodeLabel(configNode,val);
                                        var container = propRow.children()[1];

                                        var div = $('<span>',{class:""}).appendTo(container);
                                        var nodeDiv = $('<div>',{class:"red-ui-palette-node red-ui-palette-node-small"}).appendTo(div);
                                        var colour = RED.utils.getNodeColor(configNode.type,configNode._def);
                                        var icon_url = RED.utils.getNodeIcon(configNode._def);
                                        nodeDiv.css({'backgroundColor':colour, "cursor":"pointer"});
                                        var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
                                        $('<div/>',{class:"red-ui-palette-icon",style:"background-image: url("+icon_url+")"}).appendTo(iconContainer);
                                        var nodeContainer = $('<span></span>').css({"verticalAlign":"top","marginLeft":"6px"}).text(configLabel).appendTo(container);

                                        nodeDiv.on('dblclick',function() {
                                            RED.editor.editConfig("", configNode.type, configNode.id);
                                        })

                                    }
                                } else {
                                    RED.utils.createObjectElement(val,{sourceId: node.id}).appendTo(propRow.children()[1]);
                                }
                            }
                        }
                    }
                    if (count > 0) {
                        $('<a href="#" class="node-info-property-header'+(expandedSections.property?" expanded":"")+'"><span class="red-ui-help-property-more">'+RED._("sidebar.info.showMore")+'</span><span class="red-ui-help-property-less">'+RED._("sidebar.info.showLess")+'</span> <i class="fa fa-caret-down"></i></a>').appendTo(blankRow.children()[0]);
                    }
                }
                if (node.type !== 'tab') {
                    if (subflowRegex) {
                        $('<tr class="blank"><th colspan="2">'+RED._("sidebar.info.subflow")+'</th></tr>').appendTo(tableBody);
                        $('<tr class="node-info-subflow-row"><td>'+RED._("common.label.name")+'</td><td><span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(subflowNode.name)+'">'+RED.utils.sanitize(subflowNode.name)+'</span></td></tr>').appendTo(tableBody);
                    }
                }
            }
            if (subflowRegex) {
                propRow = $('<tr class="red-ui-help-info-row"><td>'+RED._("subflow.category")+'</td><td></td></tr>').appendTo(tableBody);
                var category = subflowNode.category||"subflows";
                $(propRow.children()[1]).text(RED._("palette.label."+category,{defaultValue:category}))
                $('<tr class="node-info-subflow-row"><td>'+RED._("sidebar.info.instances")+"</td><td>"+subflowUserCount+'</td></tr>').appendTo(tableBody);
                if (subflowNode.meta) {
                    propRow = $('<tr class="red-ui-help-info-row"><td>'+RED._("subflow.module")+'</td><td></td></tr>').appendTo(tableBody);
                    $(propRow.children()[1]).text(subflowNode.meta.module||"")
                    propRow = $('<tr class="red-ui-help-info-row"><td>'+RED._("subflow.version")+'</td><td></td></tr>').appendTo(tableBody);
                    $(propRow.children()[1]).text(subflowNode.meta.version||"")
                }
            }

            var infoText = "";

            if (node._def && node._def.info) {
                var info = node._def.info;
                var textInfo = (typeof info === "function" ? info.call(node) : info);
                infoText = infoText + RED.utils.renderMarkdown(textInfo);
            }
            if (node.info) {
                infoText = infoText + RED.utils.renderMarkdown(node.info || "")
            }
            var infoSectionContainer = $("<div>").css("padding","0 6px 6px").appendTo(propertiesPanelContent)

            setInfoText(infoText, infoSectionContainer);

            $(".red-ui-sidebar-info-stack").scrollTop(0);
            $(".node-info-property-header").on("click", function(e) {
                e.preventDefault();
                expandedSections["property"] = !expandedSections["property"];
                $(this).toggleClass("expanded",expandedSections["property"]);
                $(".red-ui-help-info-property-row").toggle(expandedSections["property"]);
            });
        }


        // $('<tr class="blank"><th colspan="2"></th></tr>').appendTo(tableBody);
        // propRow = $('<tr class="red-ui-help-info-row"><td>Actions</td><td></td></tr>').appendTo(tableBody);
        // var actionBar = $(propRow.children()[1]);
        //
        // // var actionBar = $('<div>',{style:"background: #fefefe; padding: 3px;"}).appendTo(propertiesPanel);
        // $('<button type="button" class="red-ui-button"><i class="fa fa-code"></i></button>').appendTo(actionBar);
        // $('<button type="button" class="red-ui-button"><i class="fa fa-code"></i></button>').appendTo(actionBar);
        // $('<button type="button" class="red-ui-button"><i class="fa fa-code"></i></button>').appendTo(actionBar);
        // $('<button type="button" class="red-ui-button"><i class="fa fa-code"></i></button>').appendTo(actionBar);



    }

    function setInfoText(infoText,target) {
        var info = addTargetToExternalLinks($('<div class="red-ui-help"><span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(infoText)+'">'+infoText+'</span></div>')).appendTo(target);
        info.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" );
        var foldingHeader = "H3";
        info.find(foldingHeader).wrapInner('<a class="red-ui-help-info-header expanded" href="#"></a>')
            .find("a").prepend('<i class="fa fa-angle-right">').on("click", function(e) {
                e.preventDefault();
                var isExpanded = $(this).hasClass('expanded');
                var el = $(this).parent().next();
                while(el.length === 1 && el[0].nodeName !== foldingHeader) {
                    el.toggle(!isExpanded);
                    el = el.next();
                }
                $(this).toggleClass('expanded',!isExpanded);
            });
        RED.editor.mermaid.render()
    }

    var tips = (function() {
        var enabled = true;
        var startDelay = 1000;
        var cycleDelay = 15000;
        var startTimeout;
        var refreshTimeout;
        var tipCount = -1;

        RED.actions.add("core:toggle-show-tips",function(state) {
            if (state === undefined) {
                RED.userSettings.toggle("view-show-tips");
            } else {
                enabled = state;
                if (enabled) {
                    startTips();
                } else {
                    stopTips();
                }
            }
        });

        function setTip() {
            var r = Math.floor(Math.random() * tipCount);
            var tip = RED._("infotips:info.tip"+r);

            var m;
            while ((m=/({{(.*?)}})/.exec(tip))) {
                var shortcut = RED.keyboard.getShortcut(m[2]);
                if (shortcut) {
                    tip = tip.replace(m[1],RED.keyboard.formatKey(shortcut.key));
                } else {
                    return;
                }
            }
            while ((m=/(\[([a-z]*?)\])/.exec(tip))) {
                tip = tip.replace(m[1],RED.keyboard.formatKey(m[2]));
            }
            tipBox.html(tip).fadeIn(200);
            if (startTimeout) {
                startTimeout = null;
                refreshTimeout = setInterval(cycleTips,cycleDelay);
            }
        }
        function cycleTips() {
            tipBox.fadeOut(300,function() {
                setTip();
            })
        }
        function startTips() {
            $(".red-ui-sidebar-info").addClass('show-tips');
            resizeStack();
            if (enabled) {
                if (!startTimeout && !refreshTimeout) {
                    if (tipCount === -1) {
                        do {
                            tipCount++;
                        } while(RED._("infotips:info.tip"+tipCount)!=="info.tip"+tipCount);
                    }
                    startTimeout = setTimeout(setTip,startDelay);
                }
            }
        }
        function stopTips() {
            $(".red-ui-sidebar-info").removeClass('show-tips');
            resizeStack();
            clearInterval(refreshTimeout);
            clearTimeout(startTimeout);
            refreshTimeout = null;
            startTimeout = null;
        }
        function nextTip() {
            clearInterval(refreshTimeout);
            startTimeout = true;
            setTip();
        }
        return {
            start: startTips,
            stop: stopTips,
            next: nextTip,
            enabled: function() { return enabled; }
        }
    })();

    function clear() {
        // sections.hide();
        refresh(null);
    }

    function set(html,title) {
        console.warn("Deprecated use of RED.sidebar.info.set - use RED.sidebar.help.set instead")
        RED.sidebar.help.set(html,title);
    }

    function refreshSelection(selection) {
        if (selection === undefined) {
            selection = RED.view.selection();
        }
        if (selection.nodes) {
            if (selection.nodes.length == 1) {
                var node = selection.nodes[0];
                if (node.type === "subflow" && node.direction) {
                    refresh(RED.nodes.subflow(node.z));
                } else {
                    refresh(node);
                }
            } else {
                refresh(selection.nodes);
            }
        } else if (selection.flows || selection.subflows) {
            refresh(selection.flows);
        } else {
            var activeWS = RED.workspaces.active();

            var flow = RED.nodes.workspace(activeWS) || RED.nodes.subflow(activeWS);
            if (flow) {
                refresh(flow);
            } else {
                var workspace = RED.nodes.workspace(RED.workspaces.active());
                if (workspace && workspace.info) {
                    refresh(workspace);
                } else {
                    refresh(null)
                    // clear();
                }
            }
        }
    }


    RED.events.on("view:selection-changed",refreshSelection);

    return {
        init: init,
        show: show,
        refresh: refresh,
        clear: clear,
        set: set
    }
})();
