/**
 * 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.projects.settings = (function() {

    var trayWidth = 700;
    var settingsVisible = false;

    var panes = [];

    function addPane(options) {
        panes.push(options);
    }

    // TODO: DRY - tab-info.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 show(initialTab) {
        if (settingsVisible) {
            return;
        }
        if (!RED.user.hasPermission("projects.write")) {
            RED.notify(RED._("user.errors.notAuthorized"),"error");
            return;
        }

        settingsVisible = true;

        var trayOptions = {
            title: RED._("sidebar.project.projectSettings.title"),
            buttons: [
                {
                    id: "node-dialog-ok",
                    text: RED._("common.label.close"),
                    class: "primary",
                    click: function() {
                        RED.tray.close();
                    }
                }
            ],
            resize: function(dimensions) {
                trayWidth = dimensions.width;
            },
            open: function(tray) {
                var project = RED.projects.getActiveProject();

                var trayBody = tray.find('.red-ui-tray-body');
                var settingsContent = $('<div></div>').appendTo(trayBody);
                var tabContainer = $('<div></div>',{class:"red-ui-settings-tabs-container"}).appendTo(settingsContent);

                $('<ul></ul>',{id:"user-settings-tabs"}).appendTo(tabContainer);
                var settingsTabs = RED.tabs.create({
                    id: "user-settings-tabs",
                    vertical: true,
                    onchange: function(tab) {
                        setTimeout(function() {
                            tabContents.children().hide();
                            $("#" + tab.id).show();
                            if (tab.pane.focus) {
                                tab.pane.focus();
                            }
                        },50);
                    }
                });
                var tabContents = $('<div></div>',{class:"red-ui-settings-tabs-content"}).appendTo(settingsContent);

                panes.forEach(function(pane) {
                    settingsTabs.addTab({
                        id: "red-ui-project-settings-tab-"+pane.id,
                        label: pane.title,
                        pane: pane
                    });
                    pane.get(project).hide().appendTo(tabContents);
                });
                settingsContent.i18n();
                settingsTabs.activateTab("red-ui-project-settings-tab-"+(initialTab||'main'))
                $("#red-ui-sidebar-shade").show();
            },
            close: function() {
                settingsVisible = false;
                panes.forEach(function(pane) {
                    if (pane.close) {
                        pane.close();
                    }
                });
                $("#red-ui-sidebar-shade").hide();

            },
            show: function() {}
        }
        if (trayWidth !== null) {
            trayOptions.width = trayWidth;
        }
        RED.tray.show(trayOptions);
    }

    function editDescription(activeProject, container) {
        RED.editor.editMarkdown({
            title: RED._('sidebar.project.editDescription'),
            header: $('<span><i class="fa fa-book"></i> README.md</span>'),
            value: activeProject.description,
            stateId: "sidebar.project.editDescription",
            complete: function(v) {
                container.empty();
                var spinner = utils.addSpinnerOverlay(container);
                var done = function(err,res) {
                    if (err) {
                        return editDescription(activeProject, container);
                    }
                    activeProject.description = v;
                    updateProjectDescription(activeProject, container);
                }
                utils.sendRequest({
                    url: "projects/"+activeProject.name,
                    type: "PUT",
                    responses: {
                        0: function(error) {
                            done(error,null);
                        },
                        200: function(data) {
                            done(null,data);
                            RED.sidebar.versionControl.refresh(true);
                        },
                        400: {
                            '*': function(error) {
                                utils.reportUnexpectedError(error);
                                done(error,null);
                            }
                        },
                    }
                },{description:v}).always(function() {
                    spinner.remove();
                });
            }
        });
    }
    function updateProjectDescription(activeProject, container) {
        container.empty();
        var desc;
        if (activeProject.description) {
            desc = RED.utils.renderMarkdown(activeProject.description);
        } else {
            desc = '<span class="red-ui-help-info-none">' + RED._("sidebar.project.noDescriptionAvailable") + '</span>';
        }
        var description = addTargetToExternalLinks($('<span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(desc)+'">'+desc+'</span>')).appendTo(container);
        description.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" );
        setTimeout(function () {
            RED.editor.mermaid.render()
        }, 200);
    }

    function editSummary(activeProject, summary, container, version, versionContainer) {
        var editButton = container.prev();
        editButton.hide();
        container.empty();
        versionContainer.empty();
        var bg = $('<span class="button-row" style="position: relative; float: right; margin-right:0;"></span>').appendTo(container);
        var input = $('<input type="text" style="width: calc(100% - 150px); margin-right: 10px;">').val(summary||"").appendTo(container);
        var versionInput = $('<input type="text" style="width: calc(100% - 150px); margin-right: 10px;">').val(version||"").appendTo(versionContainer);

        $('<button class="red-ui-button">' + RED._("common.label.cancel") + '</button>')
            .appendTo(bg)
            .on("click", function(evt) {
                evt.preventDefault();
                updateProjectSummary(activeProject.summary, container);
                updateProjectVersion(activeProject.version, versionContainer);
                editButton.show();
            });
        $('<button class="red-ui-button">' + RED._("common.label.save") + '</button>')
            .appendTo(bg)
            .on("click", function(evt) {
                evt.preventDefault();
                var newSummary = input.val();
                var newVersion = versionInput.val();
                updateProjectSummary(newSummary, container);
                updateProjectVersion(newVersion, versionContainer);
                var spinner = utils.addSpinnerOverlay(container).addClass('red-ui-component-spinner-contain');
                var done = function(err,res) {
                    if (err) {
                        spinner.remove();
                        return editSummary(activeProject, summary, container, version, versionContainer);
                    }
                    activeProject.summary = newSummary;
                    activeProject.version = newVersion;
                    spinner.remove();
                    updateProjectSummary(activeProject.summary, container);
                    updateProjectVersion(activeProject.version, versionContainer);
                    editButton.show();
                }
                utils.sendRequest({
                    url: "projects/"+activeProject.name,
                    type: "PUT",
                    responses: {
                        0: function(error) {
                            done(error,null);
                        },
                        200: function(data) {
                            RED.sidebar.versionControl.refresh(true);
                            done(null,data);
                        },
                        400: {
                            '*': function(error) {
                                utils.reportUnexpectedError(error);
                                done(error,null);
                            }
                        },
                    }
                },{summary:newSummary, version: newVersion});
            });
    }
    function updateProjectSummary(summary, container) {
        container.empty();
        if (summary) {
            container.text(summary).removeClass('red-ui-help-info-none');
        } else {
            container.text(RED._("sidebar.project.noSummaryAvailable")).addClass('red-ui-help-info-none');
        }
    }
    function updateProjectVersion(version, container) {
        container.empty();
        if (version) {
            container.text(version);
        }
    }
    function createMainPane(activeProject) {

        var pane = $('<div id="red-ui-project-settings-tab-main" class="red-ui-project-settings-tab-pane red-ui-help"></div>');
        $('<h1>').text(activeProject.name).appendTo(pane);
        var summary = $('<div style="position: relative">').appendTo(pane);
        var summaryContent = $('<div></div>').appendTo(summary);
        var versionContent = $('<div></div>').addClass('red-ui-help-info-none').appendTo(summary);
        updateProjectSummary(activeProject.summary, summaryContent);
        updateProjectVersion(activeProject.version, versionContent);

        if (RED.user.hasPermission("projects.write")) {
            $('<button class="red-ui-button red-ui-button-small" style="float: right;">' + RED._('sidebar.project.editDescription') + '</button>')
                .prependTo(summary)
                .on("click", function(evt) {
                    evt.preventDefault();
                    editSummary(activeProject, activeProject.summary, summaryContent, activeProject.version, versionContent);
                });
        }
        $('<hr>').appendTo(pane);

        var description = $('<div class="red-ui-help" style="position: relative"></div>').appendTo(pane);
        var descriptionContent = $('<div>',{style:"min-height: 200px"}).appendTo(description);

        updateProjectDescription(activeProject, descriptionContent);

        if (RED.user.hasPermission("projects.write")) {
            $('<button class="red-ui-button red-ui-button-small" style="float: right;">' + RED._('sidebar.project.editReadme') + '</button>')
                .prependTo(description)
                .on("click", function(evt) {
                    evt.preventDefault();
                    editDescription(activeProject, descriptionContent);
                });
        }
        return pane;
    }
    function updateProjectDependencies(activeProject,depsList) {
        depsList.editableList('empty');

        var totalCount = 0;
        var unknownCount = 0;
        var unusedCount = 0;
        var notInstalledCount = 0;

        for (var m in modulesInUse) {
            if (modulesInUse.hasOwnProperty(m) && !activeProject.dependencies.hasOwnProperty(m)) {
                depsList.editableList('addItem',{
                    id: modulesInUse[m].module,
                    version: modulesInUse[m].version,
                    count: modulesInUse[m].count,
                    known: activeProject.dependencies.hasOwnProperty(m),
                    installed: true
                });
                totalCount++;
                if (modulesInUse[m].count === 0) {
                    unusedCount++;
                }
                if (!activeProject.dependencies.hasOwnProperty(m)) {
                    unknownCount++;
                }
            }
        }

        if (activeProject.dependencies) {
            for (var m in activeProject.dependencies) {
                if (activeProject.dependencies.hasOwnProperty(m)) {
                    var installed = !!RED.nodes.registry.getModule(m) && activeProject.dependencies[m] === modulesInUse[m]?.version;
                    depsList.editableList('addItem',{
                        id: m,
                        version: activeProject.dependencies[m], //RED.nodes.registry.getModule(module).version,
                        count: 0,
                        known: true,
                        installed: installed
                    });
                    totalCount++;
                    if (installed) {
                        unusedCount++;
                    } else {
                        notInstalledCount++;
                    }
                }
            }
        }
        // if (notInstalledCount > 0) {
        //     depsList.editableList('addItem',{index:1, label:"Missing dependencies"}); // TODO: nls
        // }
        // if (unknownCount > 0) {
        //     depsList.editableList('addItem',{index:1, label:"Unlisted dependencies"}); // TODO: nls
        // }
        // if (unusedCount > 0) {
        //     depsList.editableList('addItem',{index:3, label:"Unused dependencies"}); // TODO: nls
        // }
        if (totalCount === 0) {
            depsList.editableList('addItem',{index:0, label:RED._("sidebar.project.projectSettings.none")});
        }

    }

    function saveDependencies(depsList,container,dependencies,complete) {
        var activeProject = RED.projects.getActiveProject();
        var spinner = utils.addSpinnerOverlay(container).addClass('red-ui-component-spinner-contain');
        var done = function(err,res) {
            spinner.remove();
            if (err) {
                return complete(err);
            }
            activeProject.dependencies = dependencies;
            RED.sidebar.versionControl.refresh(true);
            complete();
        }
        utils.sendRequest({
            url: "projects/"+activeProject.name,
            type: "PUT",
            responses: {
                0: function(error) {
                    done(error,null);
                },
                200: function(data) {
                    RED.sidebar.versionControl.refresh(true);
                    done(null,data);
                },
                400: {
                    '*': function(error) {
                        done(error,null);
                    }
                },
            }
        },{dependencies:dependencies});
    }
    function editDependencies(activeProject,depsJSON,container,depsList) {
        var json = depsJSON||JSON.stringify(activeProject.dependencies||{},"",4);
        if (json === "{}") {
            json = "{\n\n}";
        }
        RED.editor.editJSON({
            title: RED._('sidebar.project.editDependencies'),
            value: json,
            requireValid: true,
            complete: function(v) {
                try {
                    var parsed = JSON.parse(v);
                    saveDependencies(depsList,container,parsed,function(err) {
                        if (err) {
                            return editDependencies(activeProject,v,container,depsList);
                        }
                        activeProject.dependencies = parsed;
                        updateProjectDependencies(activeProject,depsList);
                    });
                } catch(err) {
                    editDependencies(activeProject,v,container,depsList);
                }
            }
        });
    }

    function createDependenciesPane(activeProject) {
        var pane = $('<div id="red-ui-project-settings-tab-deps" class="red-ui-project-settings-tab-pane red-ui-help"></div>');
        if (RED.user.hasPermission("projects.write")) {
            $('<button class="red-ui-button red-ui-button-small" style="margin-top:10px;float: right;">' + RED._("sidebar.project.projectSettings.edit") + '</button>')
                .appendTo(pane)
                .on("click", function(evt) {
                    evt.preventDefault();
                    editDependencies(activeProject,null,pane,depsList)
                });
        }
        var depsList = $("<ol>",{style:"position: absolute;top: 60px;bottom: 20px;left: 20px;right: 20px;"}).appendTo(pane);
        depsList.editableList({
            addButton: false,
            addItem: function(row,index,entry) {
                // console.log(entry);
                var headerRow = $('<div>',{class:"red-ui-palette-module-header"}).appendTo(row);
                if (entry.label) {
                    if (entry.index === 0) {
                        headerRow.addClass("red-ui-search-empty")
                    } else {
                        row.parent().addClass("red-ui-palette-module-section");
                    }
                    headerRow.text(entry.label);
                    // if (RED.user.hasPermission("projects.write")) {
                    //     if (entry.index === 1) {
                    //         var addButton = $('<button class="red-ui-button red-ui-button-small red-ui-palette-module-button">add to project</button>').appendTo(headerRow).on("click", function(evt) {
                    //             evt.preventDefault();
                    //             var deps = $.extend(true, {}, activeProject.dependencies);
                    //             for (var m in modulesInUse) {
                    //                 if (modulesInUse.hasOwnProperty(m) && !modulesInUse[m].known) {
                    //                     deps[m] = modulesInUse[m].version;
                    //                 }
                    //             }
                    //             editDependencies(activeProject,JSON.stringify(deps,"",4),pane,depsList);
                    //         });
                    //     } else if (entry.index === 3) {
                    //         var removeButton = $('<button class="red-ui-button red-ui-button-small red-ui-palette-module-button">remove from project</button>').appendTo(headerRow).on("click", function(evt) {
                    //             evt.preventDefault();
                    //             var deps = $.extend(true, {}, activeProject.dependencies);
                    //             for (var m in activeProject.dependencies) {
                    //                 if (activeProject.dependencies.hasOwnProperty(m) && !modulesInUse.hasOwnProperty(m)) {
                    //                     delete deps[m];
                    //                 }
                    //             }
                    //             editDependencies(activeProject,JSON.stringify(deps,"",4),pane,depsList);
                    //         });
                    //     }
                    // }
                } else {
                    headerRow.addClass("red-ui-palette-module-header");
                    if (!entry.installed) {
                        headerRow.addClass("red-ui-palette-module-not-installed");
                    } else if (entry.count === 0) {
                        headerRow.addClass("red-ui-palette-module-unused");
                    } else if (!entry.known) {
                        headerRow.addClass("red-ui-palette-module-unknown");
                    }

                    entry.element = headerRow;
                    var titleRow = $('<div class="red-ui-palette-module-meta red-ui-palette-module-name"></div>').appendTo(headerRow);
                    var iconClass = "fa-cube";
                    if (!entry.installed) {
                        iconClass = "fa-warning";
                    }
                    var icon = $('<i class="fa '+iconClass+'"></i>').appendTo(titleRow);
                    entry.icon = icon;
                    $('<span>').text(entry.id).appendTo(titleRow);
                    var metaRow = $('<div class="red-ui-palette-module-meta red-ui-palette-module-version"><i class="fa fa-tag"></i></div>').appendTo(headerRow);
                    var versionSpan = $('<span>').text(entry.version).appendTo(metaRow);
                    metaRow = $('<div class="red-ui-palette-module-meta"></div>').appendTo(headerRow);
                    var buttons = $('<div class="red-ui-palette-module-button-group"></div>').appendTo(metaRow);
                    if (RED.user.hasPermission("projects.write")) {
                        if (!entry.installed && RED.settings.get('externalModules.palette.allowInstall', true) !== false) {
                            $('<a href="#" class="red-ui-button red-ui-button-small">' + RED._("sidebar.project.projectSettings.install") + '</a>').appendTo(buttons)
                                .on("click", function(evt) {
                                    evt.preventDefault();
                                    RED.palette.editor.install(entry,row,function(err) {
                                        if (!err) {
                                            entry.installed = true;
                                            var spinner = RED.utils.addSpinnerOverlay(row,true);
                                            setTimeout(function() {
                                                depsList.editableList('removeItem',entry);
                                                refreshModuleInUseCounts();
                                                if (modulesInUse.hasOwnProperty(entry.id)) {
                                                    entry.count = modulesInUse[entry.id].count;
                                                } else {
                                                    entry.count = 0;
                                                }
                                                depsList.editableList('addItem',entry);
                                            },500);
                                        }
                                    });
                                })
                        } else if (entry.known && entry.count === 0) {
                            $('<a href="#" class="red-ui-button red-ui-button-small">' + RED._("sidebar.project.projectSettings.removeFromProject") + '</a>').appendTo(buttons)
                                .on("click", function(evt) {
                                    evt.preventDefault();
                                    var deps = $.extend(true, {}, activeProject.dependencies);
                                    delete deps[entry.id];
                                    saveDependencies(depsList,row,deps,function(err) {
                                        if (!err) {
                                            row.fadeOut(200,function() {
                                                depsList.editableList('removeItem',entry);
                                            });
                                        } else {
                                            console.log(err);
                                        }
                                    });
                                });
                        } else if (!entry.known) {
                            $('<a href="#" class="red-ui-button red-ui-button-small">' + RED._("sidebar.project.projectSettings.addToProject") + '</a>').appendTo(buttons)
                                .on("click", function(evt) {
                                    evt.preventDefault();
                                    var deps = $.extend(true, {}, activeProject.dependencies);
                                    deps[entry.id] = modulesInUse[entry.id].version;
                                    saveDependencies(depsList,row,deps,function(err) {
                                        if (!err) {
                                            buttons.remove();
                                            headerRow.removeClass("red-ui-palette-module-unknown");
                                        } else {
                                            console.log(err);
                                        }
                                    });
                                });
                        }
                    }
                }
            },
            sort: function(A,B) {
                return A.id.localeCompare(B.id);
                // if (A.index && B.index) {
                //     return A.index - B.index;
                // }
                // var Acategory = A.index?A.index:(A.known?(A.count>0?0:4):2);
                // var Bcategory = B.index?B.index:(B.known?(B.count>0?0:4):2);
                // if (Acategory === Bcategory) {
                //     return A.id.localeCompare(B.id);
                // } else {
                //     return Acategory - Bcategory;
                // }
            }
        });

        updateProjectDependencies(activeProject,depsList);
        return pane;

    }

    function showProjectFileListing(row,activeProject,current,selectFilter,done) {
        var dialog;
        var dialogBody;
        var filesList;
        var selected;
        var container = $('<div class="red-ui-projects-file-listing-container"></div>',{style:"position: relative; min-height: 175px; height: 175px;"}).hide().appendTo(row);
        var spinner = utils.addSpinnerOverlay(container);
        $.getJSON("projects/"+activeProject.name+"/files",function(result) {
            var fileNames = Object.keys(result);
            fileNames = fileNames.filter(function(fn) {
                return !result[fn].status || !/D/.test(result[fn].status);
            })
            var files = {};
            fileNames.sort();
            fileNames.forEach(function(file) {
                file.split("/").reduce(function(r,v,i,arr) { if (v) { if (i<arr.length-1) { r[v] = r[v]||{};} else { r[v] = true }return r[v];}},files);
            });
            var sortFiles = function(key,value,fullPath) {
                var result = {
                    name: key||"/",
                    path: fullPath+(fullPath?"/":"")+key,
                };
                if (value === true) {
                    result.type = 'f';
                    return result;
                }
                result.type = 'd';
                result.children = [];
                result.path = result.path;
                var files = Object.keys(value);
                files.forEach(function(file) {
                    result.children.push(sortFiles(file,value[file],result.path));
                })
                result.children.sort(function(A,B) {
                    if (A.hasOwnProperty("children") && !B.hasOwnProperty("children")) {
                        return -1;
                    } else if (!A.hasOwnProperty("children") && B.hasOwnProperty("children")) {
                        return 1;
                    }
                    return A.name.localeCompare(B.name);
                })
                return result;
            }
            var files = sortFiles("",files,"")

            createFileSubList(container,files.children,current,selectFilter,done,"height: 175px");
            spinner.remove();
        });
        return container;
    }

    function createFileSubList(container, files, current, selectFilter, onselect, style) {
        style = style || "";
        var list = $('<ol>',{class:"red-ui-projects-dialog-file-list", style:style}).appendTo(container).editableList({
            addButton: false,
            scrollOnAdd: false,
            addItem: function(row,index,entry) {
                var header = $('<div></div>',{class:"red-ui-projects-dialog-file-list-entry"}).appendTo(row);
                if (entry.children) {
                    $('<span class="red-ui-projects-dialog-file-list-entry-folder"><i class="fa fa-angle-right"></i> <i class="fa fa-folder-o"></i></span>').appendTo(header);
                    if (entry.children.length > 0) {
                        var children = $('<div></div>',{style:"padding-left: 20px;"}).appendTo(row);
                        if (current.indexOf(entry.path+"/") === 0) {
                            header.addClass("expanded");
                        } else {
                            children.hide();
                        }
                        createFileSubList(children,entry.children,current,selectFilter,onselect);
                        header.addClass("selectable");
                        header.on("click", function(e) {
                            if ($(this).hasClass("expanded")) {
                                $(this).removeClass("expanded");
                                children.slideUp(200);
                            } else {
                                $(this).addClass("expanded");
                                children.slideDown(200);
                            }

                        });

                    }
                } else {
                    var fileIcon = "fa-file-o";
                    var fileClass = "";
                    if (/\.json$/i.test(entry.name)) {
                        fileIcon = "fa-file-code-o"
                    } else if (/\.md$/i.test(entry.name)) {
                        fileIcon = "fa-book";
                    } else if (/^\.git/i.test(entry.name)) {
                        fileIcon = "fa-code-fork";
                        header.addClass("red-ui-projects-dialog-file-list-entry-file-type-git");
                    }
                    $('<span class="red-ui-projects-dialog-file-list-entry-file"> <i class="fa '+fileIcon+'"></i></span>').appendTo(header);
                    if (selectFilter(entry)) {
                        header.addClass("selectable");
                        if (entry.path === current) {
                            header.addClass("selected");
                        }
                        header.on("click", function(e) {
                            $(".red-ui-projects-dialog-file-list-entry.selected").removeClass("selected");
                            $(this).addClass("selected");
                            onselect(entry.path,true);
                        })
                        header.on("dblclick", function(e) {
                            e.preventDefault();
                            onselect(entry.path,true);
                        })
                    } else {
                        header.addClass("unselectable");
                    }
                }
                $('<span class="red-ui-projects-dialog-file-list-entry-name" style=""></span>').text(entry.name).appendTo(header);
            }
        });
        if (!style) {
            list.parent().css("overflow-y","");
        }
        files.forEach(function(f) {
            list.editableList('addItem',f);
        })
    }

    // function editFiles(activeProject, container,flowFile, flowFileLabel) {
    //     var editButton = container.children().first();
    //     editButton.hide();
    //
    //     var flowFileInput = $('<input id="" type="text" style="width: calc(100% - 300px);">').val(flowFile).insertAfter(flowFileLabel);
    //
    //     var flowFileInputSearch = $('<button class="red-ui-button" style="margin-left: 10px"><i class="fa fa-folder-open-o"></i></button>')
    //         .insertAfter(flowFileInput)
    //         .on("click", function(e) {
    //             showProjectFileListing(activeProject,'Select flow file',flowFileInput.val(),function(result) {
    //                 flowFileInput.val(result);
    //                 checkFiles();
    //             })
    //         })
    //
    //     var checkFiles = function() {
    //         saveButton.toggleClass('disabled',flowFileInput.val()==="");
    //         saveButton.prop('disabled',flowFileInput.val()==="");
    //     }
    //     flowFileInput.on("change keyup paste",checkFiles);
    //     flowFileLabel.hide();
    //
    //     var bg = $('<span class="button-group" style="position: relative; float: right; margin-right:0;"></span>').prependTo(container);
    //     $('<button class="red-ui-button">Cancel</button>')
    //         .appendTo(bg)
    //         .on("click", function(evt) {
    //             evt.preventDefault();
    //
    //             flowFileLabel.show();
    //             flowFileInput.remove();
    //             flowFileInputSearch.remove();
    //             bg.remove();
    //             editButton.show();
    //         });
    //     var saveButton = $('<button class="red-ui-button">Save</button>')
    //         .appendTo(bg)
    //         .on("click", function(evt) {
    //             evt.preventDefault();
    //             var newFlowFile = flowFileInput.val();
    //             var newCredsFile = credentialsFileInput.val();
    //             var spinner = utils.addSpinnerOverlay(container);
    //             var done = function(err,res) {
    //                 if (err) {
    //                     spinner.remove();
    //                     return;
    //                 }
    //                 activeProject.summary = v;
    //                 spinner.remove();
    //                 flowFileLabel.text(newFlowFile);
    //                 flowFileLabel.show();
    //                 flowFileInput.remove();
    //                 flowFileInputSearch.remove();
    //                 bg.remove();
    //                 editButton.show();
    //             }
    //             // utils.sendRequest({
    //             //     url: "projects/"+activeProject.name,
    //             //     type: "PUT",
    //             //     responses: {
    //             //         0: function(error) {
    //             //             done(error,null);
    //             //         },
    //             //         200: function(data) {
    //             //             done(null,data);
    //             //         },
    //             //         400: {
    //             //             'unexpected_error': function(error) {
    //             //                 done(error,null);
    //             //             }
    //             //         },
    //             //     }
    //             // },{summary:v});
    //         });
    //
    //
    //     checkFiles();
    //
    // }

    function createFilesSection(activeProject,pane) {
        var title = $('<h3></h3>').text(RED._("sidebar.project.projectSettings.files")).appendTo(pane);
        var filesContainer = $('<div class="red-ui-settings-section"></div>').appendTo(pane);
        if (RED.user.hasPermission("projects.write")) {
            var editFilesButton = $('<button type="button" id="red-ui-project-settings-tab-settings-file-edit" class="red-ui-button red-ui-button-small" style="float: right;">' + RED._('sidebar.project.projectSettings.edit') + '</button>')
                .appendTo(title)
                .on("click", function(evt) {
                    evt.preventDefault();
                    formButtons.show();
                    editFilesButton.hide();
                    // packageFileLabelText.hide();

                    if (!activeProject.files.package) {
                        packageFileSubLabel.find(".red-ui-projects-edit-form-sublabel-text").text(RED._("sidebar.project.projectSettings.packageCreate"));
                        packageFileSubLabel.show();
                    }

                    packageFileInputSearch.show();
                    // packageFileInputCreate.show();
                    flowFileLabelText.hide();
                    flowFileInput.show();
                    flowFileInputSearch.show();

                    flowFileInputResize();

                    // credentialStateLabel.parent().hide();
                    credentialStateLabel.addClass("uneditable-input");
                    $(".red-ui-settings-row-credentials").show();
                    credentialStateLabel.css('height','auto');
                    credentialFormRows.hide();
                    credentialSecretButtons.show();
                });
        }
        var row;

        // Flow files
        row = $('<div class="red-ui-settings-row"></div>').appendTo(filesContainer);
        $('<label for=""></label>').text(RED._("sidebar.project.projectSettings.package")).appendTo(row);
        var packageFileLabel = $('<div class="uneditable-input" style="padding:0">').appendTo(row);
        var packageFileLabelText = $('<span style="display:inline-block;  padding: 6px">').text(activeProject.files.package||"package.json").appendTo(packageFileLabel);
        var packageFileInput = $('<input type="hidden">').val(activeProject.files.package||"package.json").appendTo(packageFileLabel);

        var packageFileInputSearch = $('<button type="button" class="red-ui-button toggle single" style="border-top-right-radius: 4px; border-bottom-right-radius: 4px; width: 36px; height: 34px; position: absolute; top: -1px; right: -1px;"><i class="fa fa-folder-open-o"></i></button>')
            .hide()
            .appendTo(packageFileLabel)
            .on("click", function(e) {
                if ($(this).hasClass('selected')) {
                    $(this).removeClass('selected');
                    packageFileLabel.find('.red-ui-projects-file-listing-container').slideUp(200,function() {
                         $(this).remove();
                         packageFileLabel.css('height','');
                     });
                    packageFileLabel.css('color','');
                } else {
                    $(this).addClass('selected');
                    packageFileLabel.css('color','inherit');
                    var fileList = showProjectFileListing(packageFileLabel,activeProject,packageFileInput.val(),
                                        function(entry) { return entry.children || /package\.json$/.test(entry.path); },
                                        function(result,close) {
                                            if (result) {
                                                packageFileInput.val(result);
                                                packageFileLabelText.text(result);
                                                var rootDir = result.substring(0,result.length - 12);
                                                flowFileLabelPrefixText.text(rootDir);
                                                credFileLabelPrefixText.text(rootDir);
                                                flowFileInputResize();
                                                packageFileSubLabel.hide();
                                            }
                                            if (close) {
                                                $(packageFileInputSearch).trigger("click");
                                            }
                                            checkFiles();
                                        });
                    packageFileLabel.css('height','auto');
                    setTimeout(function() {
                        fileList.slideDown(200);
                    },50);

                }
            })
        RED.popover.tooltip(packageFileInputSearch,RED._("sidebar.project.projectSettings.selectFile"));
        var packageFileSubLabel = $('<label style="margin-left: 110px" class="red-ui-projects-edit-form-sublabel"><small><span class="form-warning"><i class="fa fa-warning"></i> <span class="red-ui-projects-edit-form-sublabel-text"></span></small></label>').appendTo(row).hide();
        if (!activeProject.files.package) {
            packageFileSubLabel.find(".red-ui-projects-edit-form-sublabel-text").text(RED._("sidebar.project.projectSettings.fileNotExist"));
            packageFileSubLabel.show();
        }


        var projectPackage = activeProject.files.package||"package.json";
        var projectRoot = projectPackage.substring(0,projectPackage.length - 12);

        // Flow files
        row = $('<div class="red-ui-settings-row"></div>').appendTo(filesContainer);
        $('<label for=""></label>').text(RED._("sidebar.project.projectSettings.flow")).appendTo(row);
        var flowFileLabel = $('<div class="uneditable-input" style="padding:0">').appendTo(row);
        var flowFileLabelPrefixText = $('<span style="display:inline-block; padding: 6px 0 6px 6px">').text(projectRoot).appendTo(flowFileLabel);
        var flowFileName = "flows.json";
        if (activeProject.files.flow) {
            if (activeProject.files.flow.indexOf(projectRoot) === 0) {
                flowFileName = activeProject.files.flow.substring(projectRoot.length);
            } else {
                flowFileName = activeProject.files.flow;
            }
        }
        var flowFileLabelText = $('<span style="display:inline-block; padding: 6px 6px 6px 0">').text(flowFileName).appendTo(flowFileLabel);
        var flowFileInputResize = function() {
            flowFileInput.css({
                "width": "calc(100% - "+(flowFileInputSearch.width() + flowFileLabelPrefixText.width())+"px)"
            });
        }
        var flowFileInput = $('<input type="text" style="padding-left:1px; margin-top: -2px; margin-bottom: 0;border: none;">').val(flowFileName).hide().appendTo(flowFileLabel);
        var flowFileInputSearch = $('<button type="button" class="red-ui-button toggle single" style="border-top-right-radius: 4px; border-bottom-right-radius: 4px; width: 36px; height: 34px; position: absolute; top: -1px; right: -1px;"><i class="fa fa-folder-open-o"></i></button>')
            .hide()
            .appendTo(flowFileLabel)
            .on("click", function(e) {
                if ($(this).hasClass('selected')) {
                    $(this).removeClass('selected');
                    flowFileLabel.find('.red-ui-projects-file-listing-container').slideUp(200,function() {
                         $(this).remove();
                         flowFileLabel.css('height','');
                     });
                    flowFileLabel.css('color','');
                } else {
                    $(this).addClass('selected');
                    flowFileLabel.css('color','inherit');
                    var packageFile = packageFileInput.val();
                    var packagePrefix = packageFile.substring(0,packageFile.length - 12);
                    var re = new RegExp("^"+packagePrefix+".*\.json$");
                    var fileList = showProjectFileListing(flowFileLabel,
                                                          activeProject,
                                                          flowFileInput.val(),
                                                          function(entry) { return !/package.json$/.test(entry.path) && re.test(entry.path) && !/_cred\.json$/.test(entry.path) },
                                                          function(result,isDblClick) {
                                                              if (result) {
                                                                  flowFileInput.val(result.substring(packagePrefix.length));

                                                              }
                                                              if (isDblClick) {
                                                                  $(flowFileInputSearch).trigger("click");
                                                              }
                                                              checkFiles();
                                                          }
                                                      );
                    flowFileLabel.css('height','auto');
                    setTimeout(function() {
                        fileList.slideDown(200);
                    },50);

                }
            })
        RED.popover.tooltip(flowFileInputSearch,RED._("sidebar.project.projectSettings.selectFile"));

        row = $('<div class="red-ui-settings-row"></div>').appendTo(filesContainer);
        $('<label for=""></label>').text(RED._("sidebar.project.projectSettings.credentials")).appendTo(row);

        var credFileName = "flows_cred.json";
        if (activeProject.files.credentials) {
            if (activeProject.files.flow.indexOf(projectRoot) === 0) {
                credFileName = activeProject.files.credentials.substring(projectRoot.length);
            } else {
                credFileName = activeProject.files.credentials;
            }
        }

        var credFileLabel = $('<div class="uneditable-input" style="padding:0">').appendTo(row);
        var credFileLabelPrefixText = $('<span style="display:inline-block;padding: 6px 0 6px 6px">').text(projectRoot).appendTo(credFileLabel);
        var credFileLabelText = $('<span style="display:inline-block; padding: 6px 6px 6px 0">').text(credFileName).appendTo(credFileLabel);

        var credFileInput = $('<input type="hidden">').val(credFileName).insertAfter(credFileLabel);

        var checkFiles = function() {
            var saveDisabled;
            var currentFlowValue = flowFileInput.val();
            var m = /^(.+?)(\.[^.]*)?$/.exec(currentFlowValue);
            if (m) {
                credFileLabelText.text(m[1]+"_cred"+(m[2]||".json"));
            } else if (currentFlowValue === "") {
                credFileLabelText.text("");
            }
            credFileInput.val(credFileLabelText.text());
            var isFlowInvalid = currentFlowValue==="" ||
                                /\.\./.test(currentFlowValue) ||
                                /\/$/.test(currentFlowValue);

            saveDisabled = isFlowInvalid || credFileLabelText.text()==="";

            if (credentialSecretExistingRow.is(":visible")) {
                credentialSecretExistingInput.toggleClass("input-error", credentialSecretExistingInput.val() === "");
                saveDisabled = saveDisabled || credentialSecretExistingInput.val() === "";
            }
            if (credentialSecretNewRow.is(":visible")) {
                credentialSecretNewInput.toggleClass("input-error", credentialSecretNewInput.val() === "");
                saveDisabled = saveDisabled || credentialSecretNewInput.val() === "";
            }


            flowFileInput.toggleClass("input-error", isFlowInvalid);
            // credFileInput.toggleClass("input-error",credFileInput.text()==="");
            saveButton.toggleClass('disabled',saveDisabled);
            saveButton.prop('disabled',saveDisabled);
        }
        flowFileInput.on("change keyup paste",checkFiles);


        // if (!activeProject.files.package) {
        //     $('<span class="form-warning"><i class="fa fa-warning"></i> Missing</span>').appendTo(packageFileLabelText);
        // }
        // if (!activeProject.files.flow) {
        //     $('<span class="form-warning"><i class="fa fa-warning"></i> Missing</span>').appendTo(flowFileLabelText);
        // }
        // if (!activeProject.files.credentials) {
        //     $('<span class="form-warning"><i class="fa fa-warning"></i> Missing</span>').appendTo(credFileLabel);
        // }


        row = $('<div class="red-ui-settings-row"></div>').appendTo(filesContainer);

        $('<label></label>').appendTo(row);
        var credentialStateLabel = $('<span><i class="user-settings-credentials-state-icon fa"></i> <span class="user-settings-credentials-state"></span></span>').appendTo(row);
        var credentialSecretButtons = $('<span class="button-group" style="margin-left: -72px;">').hide().appendTo(row);

        credentialStateLabel.css('color','#666');
        credentialSecretButtons.css('vertical-align','top');
        var credentialSecretResetButton = $('<button type="button" class="red-ui-button" style="vertical-align: top; width: 36px; margin-bottom: 10px"><i class="fa fa-trash-o"></i></button>')
            .appendTo(credentialSecretButtons)
            .on("click", function(e) {
                e.preventDefault();
                if (!$(this).hasClass('selected')) {
                    credentialSecretNewInput.val("");
                    credentialSecretExistingRow.hide();
                    credentialSecretNewRow.show();
                    $(this).addClass("selected");
                    credentialSecretEditButton.removeClass("selected");
                    credentialResetLabel.show();
                    credentialResetWarning.show();
                    credentialSetLabel.hide();
                    credentialChangeLabel.hide();

                    credentialFormRows.show();
                } else {
                    $(this).removeClass("selected");
                    credentialFormRows.hide();
                }
                checkFiles();
            });
        RED.popover.tooltip(credentialSecretResetButton,RED._("sidebar.project.projectSettings.resetTheEncryptionKey"));

        var credentialSecretEditButton = $('<button type="button" class="red-ui-button" style="border-top-right-radius: 4px; border-bottom-right-radius: 4px; vertical-align: top; width: 36px; margin-bottom: 10px"><i class="fa fa-pencil"></i></button>')
            .appendTo(credentialSecretButtons)
            .on("click", function(e) {
                e.preventDefault();
                if (!$(this).hasClass('selected')) {
                    credentialSecretExistingInput.val("");
                    credentialSecretNewInput.val("");
                    if (activeProject.settings.credentialSecretInvalid || !activeProject.settings.credentialsEncrypted) {
                        credentialSetLabel.show();
                        credentialChangeLabel.hide();
                        credentialSecretExistingRow.hide();
                    } else {
                        credentialSecretExistingRow.show();
                        credentialSetLabel.hide();
                        credentialChangeLabel.show();
                    }
                    credentialSecretNewRow.show();
                    credentialSecretEditButton.addClass("selected");
                    credentialSecretResetButton.removeClass("selected");

                    credentialResetLabel.hide();
                    credentialResetWarning.hide();
                    credentialFormRows.show();
                } else {
                    $(this).removeClass("selected");
                    credentialFormRows.hide();
                }
                checkFiles();
            })

        RED.popover.tooltip(credentialSecretEditButton,RED._("sidebar.project.projectSettings.changeTheEncryptionKey"));

        row = $('<div class="red-ui-settings-row red-ui-settings-row-credentials"></div>').hide().appendTo(filesContainer);



        var credentialFormRows = $('<div>',{style:"margin-top:10px"}).hide().appendTo(credentialStateLabel);

        var credentialSetLabel = $('<div style="margin: 20px 0 10px 5px;">' + RED._("sidebar.project.projectSettings.setTheEncryptionKey") + '</div>').hide().appendTo(credentialFormRows);
        var credentialChangeLabel = $('<div style="margin: 20px 0 10px 5px;">' + RED._("sidebar.project.projectSettings.changeTheEncryptionKey") + '</div>').hide().appendTo(credentialFormRows);
        var credentialResetLabel = $('<div style="margin: 20px 0 10px 5px;">' + RED._("sidebar.project.projectSettings.resetTheEncryptionKey") + '</div>').hide().appendTo(credentialFormRows);

        var credentialSecretExistingRow = $('<div class="red-ui-settings-row red-ui-settings-row-credentials"></div>').appendTo(credentialFormRows);
        $('<label for=""></label>').text(RED._("sidebar.project.projectSettings.currentKey")).appendTo(credentialSecretExistingRow);
        var credentialSecretExistingInput = $('<input type="text">').appendTo(credentialSecretExistingRow).typedInput({type:"cred"})
            .on("change keyup paste",function() {
                if (popover) {
                    popover.close();
                    popover = null;
                }
                checkFiles();
            });

        var credentialSecretNewRow = $('<div class="red-ui-settings-row red-ui-settings-row-credentials"></div>').appendTo(credentialFormRows);


        $('<label for=""></label>').text(RED._("sidebar.project.projectSettings.newKey")).appendTo(credentialSecretNewRow);
        var credentialSecretNewInput = $('<input type="text">').appendTo(credentialSecretNewRow).typedInput({type:"cred"}).on("change keyup paste",checkFiles);

        var credentialResetWarning = $('<div class="form-tips form-warning" style="margin: 10px;"><i class="fa fa-warning"></i>' + RED._("sidebar.project.projectSettings.credentialsAlert") + '</div>').hide().appendTo(credentialFormRows);


        var hideEditForm = function() {
            editFilesButton.show();
            formButtons.hide();
            // packageFileLabelText.show();
            packageFileInputSearch.hide();
            // packageFileInputCreate.hide();
            flowFileLabelText.show();
            flowFileInput.hide();
            flowFileInputSearch.hide();

            // credentialStateLabel.parent().show();
            credentialStateLabel.removeClass("uneditable-input");
            credentialStateLabel.css('height','');

            flowFileInputSearch.removeClass('selected');
            flowFileLabel.find('.red-ui-projects-file-listing-container').remove();
            flowFileLabel.css('height','');
            flowFileLabel.css('color','');

            $(".red-ui-settings-row-credentials").hide();
            credentialFormRows.hide();
            credentialSecretButtons.hide();
            credentialSecretResetButton.removeClass("selected");
            credentialSecretEditButton.removeClass("selected");


        }

        var formButtons = $('<span class="button-row" style="position: relative; float: right; margin-right:0;"></span>').hide().appendTo(filesContainer);
        $('<button type="button" class="red-ui-button">' + RED._("common.label.cancel") + '</button>')
            .appendTo(formButtons)
            .on("click", function(evt) {
                evt.preventDefault();
                var projectPackage = activeProject.files.package||"package.json";
                var projectRoot = projectPackage.substring(0,projectPackage.length - 12);
                flowFileLabelPrefixText.text(projectRoot);
                credFileLabelPrefixText.text(projectRoot);
                packageFileLabelText.text(activeProject.files.package||"package.json");
                if (!activeProject.files.package) {
                    packageFileSubLabel.find(".red-ui-projects-edit-form-sublabel-text").text(RED._("sidebar.project.projectSettings.fileNotExist"));
                    packageFileSubLabel.show();
                } else {
                    packageFileSubLabel.hide();
                }
                flowFileInput.val(flowFileLabelText.text());
                credFileLabelText.text(credFileName);
                hideEditForm();
            });
        var saveButton = $('<button type="button" class="red-ui-button">' + RED._("common.label.save") + '</button>')
            .appendTo(formButtons)
            .on("click", function(evt) {
                evt.preventDefault();
                var spinner = utils.addSpinnerOverlay(filesContainer);
                var done = function(err) {
                    spinner.remove();
                    if (err) {
                        utils.reportUnexpectedError(err);
                        return;
                    }
                    flowFileLabelText.text(flowFileInput.val());
                    credFileLabelText.text(credFileInput.val());
                    packageFileSubLabel.hide();
                    hideEditForm();
                }
                var rootPath = packageFileInput.val();
                rootPath = rootPath.substring(0,rootPath.length-12);
                var payload = {
                    files: {
                        package: packageFileInput.val(),
                        flow: rootPath+flowFileInput.val(),
                        credentials: rootPath+credFileInput.val()
                    }
                }

                if (credentialSecretResetButton.hasClass('selected')) {
                    payload.resetCredentialSecret = true;
                }
                if (credentialSecretResetButton.hasClass('selected') || credentialSecretEditButton.hasClass('selected')) {
                    payload.credentialSecret = credentialSecretNewInput.val();
                    if (credentialSecretExistingRow.is(":visible")) {
                        payload.currentCredentialSecret = credentialSecretExistingInput.val();
                    }
                }
                RED.deploy.setDeployInflight(true);
                utils.sendRequest({
                    url: "projects/"+activeProject.name,
                    type: "PUT",
                    responses: {
                        0: function(error) {
                            done(error);
                        },
                        200: function(data) {
                            activeProject = data;
                            RED.sidebar.versionControl.refresh(true);
                            updateForm();
                            done();
                        },
                        400: {
                            'credentials_load_failed': function(error) {
                                done(error);
                            },
                            'missing_current_credential_key':  function(error) {
                                credentialSecretExistingInput.addClass("input-error");
                                popover = RED.popover.create({
                                    target: credentialSecretExistingInput,
                                    direction: 'right',
                                    size: 'small',
                                    content: "Incorrect key",
                                    autoClose: 3000
                                }).open();
                                done(error);
                            },
                            '*': function(error) {
                                done(error);
                            }
                        },
                    }
                },payload).always(function() {
                    setTimeout(function() {
                        RED.deploy.setDeployInflight(false);
                    },500);
                });
            });
        var updateForm = function() {
            if (activeProject.settings.credentialSecretInvalid) {
                credentialStateLabel.find(".user-settings-credentials-state-icon").removeClass().addClass("user-settings-credentials-state-icon fa fa-warning");
                credentialStateLabel.find(".user-settings-credentials-state").text(RED._("sidebar.project.projectSettings.invalidEncryptionKey"));
            } else if (activeProject.settings.credentialsEncrypted) {
                credentialStateLabel.find(".user-settings-credentials-state-icon").removeClass().addClass("user-settings-credentials-state-icon fa fa-lock");
                credentialStateLabel.find(".user-settings-credentials-state").text(RED._("sidebar.project.projectSettings.encryptionEnabled"));
            } else {
                credentialStateLabel.find(".user-settings-credentials-state-icon").removeClass().addClass("user-settings-credentials-state-icon fa fa-unlock");
                credentialStateLabel.find(".user-settings-credentials-state").text(RED._("sidebar.project.projectSettings.encryptionDisabled"));
            }
            credentialSecretResetButton.toggleClass('disabled',!activeProject.settings.credentialSecretInvalid && !activeProject.settings.credentialsEncrypted);
            credentialSecretResetButton.prop('disabled',!activeProject.settings.credentialSecretInvalid && !activeProject.settings.credentialsEncrypted);
        }

        checkFiles();
        updateForm();
    }

    function createLocalBranchListSection(activeProject,pane) {
        var localBranchContainer = $('<div class="red-ui-settings-section"></div>').appendTo(pane);
        $('<h4></h4>').text(RED._("sidebar.project.projectSettings.branches")).appendTo(localBranchContainer);

        var row = $('<div class="red-ui-settings-row red-ui-projects-dialog-list"></div>').appendTo(localBranchContainer);


        var branchList = $('<ol>').appendTo(row).editableList({
            height: 'auto',
            addButton: false,
            scrollOnAdd: false,
            addItem: function(row,index,entry) {
                var container = $('<div class="red-ui-projects-dialog-list-entry">').appendTo(row);
                if (entry.empty) {
                    container.addClass('red-ui-search-empty');
                    container.text(RED._("sidebar.project.projectSettings.noBranches"));
                    return;
                }
                if (entry.current) {
                    container.addClass("current");
                }
                $('<span class="entry-icon"><i class="fa fa-code-fork"></i></span>').appendTo(container);
                var content = $('<span>').appendTo(container);
                var topRow = $('<div>').appendTo(content);
                $('<span class="entry-name">').text(entry.name).appendTo(topRow);
                if (entry.commit) {
                    $('<span class="entry-detail">').text(entry.commit.sha).appendTo(topRow);
                }
                if (entry.remote) {
                    var bottomRow = $('<div>').appendTo(content);

                    $('<span class="entry-detail entry-remote-name">').text(entry.remote||"").appendTo(bottomRow);
                    if (entry.status.ahead+entry.status.behind > 0) {
                        $('<span class="entry-detail">'+
                            '<i class="fa fa-long-arrow-up"></i> <span>'+entry.status.ahead+'</span> '+
                            '<i class="fa fa-long-arrow-down"></i> <span>'+entry.status.behind+'</span>'+
                            '</span>').appendTo(bottomRow);
                    }
                }

                if (!entry.current) {
                    var tools = $('<span class="entry-tools">').appendTo(container);
                    $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-trash"></i></button>')
                        .appendTo(tools)
                        .on("click", function(e) {
                            e.preventDefault();
                            var spinner = utils.addSpinnerOverlay(row).addClass('red-ui-component-spinner-contain');
                            var notification = RED.notify(RED._("sidebar.project.projectSettings.deleteConfirm", { name: entry.name }), {
                                type: "warning",
                                modal: true,
                                fixed: true,
                                buttons: [
                                    {
                                        text: RED._("common.label.cancel"),
                                        click: function() {
                                            spinner.remove();
                                            notification.close();
                                        }
                                    },{
                                        text: RED._("sidebar.project.projectSettings.deleteBranch"),
                                        click: function() {
                                            notification.close();
                                            var url = "projects/"+activeProject.name+"/branches/"+entry.name;
                                            var options = {
                                                url: url,
                                                type: "DELETE",
                                                responses: {
                                                    200: function(data) {
                                                        row.fadeOut(200,function() {
                                                            branchList.editableList('removeItem',entry);
                                                            spinner.remove();
                                                        });
                                                    },
                                                    400: {
                                                        'git_delete_branch_unmerged': function(error) {
                                                            notification = RED.notify(RED._("sidebar.project.projectSettings.unmergedConfirm", { name: entry.name }), {
                                                                type: "warning",
                                                                modal: true,
                                                                fixed: true,
                                                                buttons: [
                                                                    {
                                                                        text: RED._("common.label.cancel"),
                                                                        click: function() {
                                                                            spinner.remove();
                                                                            notification.close();
                                                                        }
                                                                    },{
                                                                        text: RED._("sidebar.project.projectSettings.deleteUnmergedBranch"),
                                                                        click: function() {
                                                                            options.url += "?force=true";
                                                                            notification.close();
                                                                            utils.sendRequest(options);
                                                                        }
                                                                    }
                                                                ]
                                                            });
                                                        },
                                                        '*': function(error) {
                                                            utils.reportUnexpectedError(error);
                                                            spinner.remove();
                                                        }
                                                    },
                                                }
                                            }
                                            utils.sendRequest(options);
                                        }
                                    }

                                ]
                            })
                        })
                }

            }
        });

        $.getJSON("projects/"+activeProject.name+"/branches",function(result) {
            if (result.branches) {
                if (result.branches.length > 0) {
                    result.branches.sort(function(A,B) {
                        if (A.current) { return -1 }
                        if (B.current) { return 1 }
                        return A.name.localeCompare(B.name);
                    });
                    result.branches.forEach(function(branch) {
                        branchList.editableList('addItem',branch);
                    })
                } else {
                    branchList.editableList('addItem',{empty:true});
                }
            }
        })
    }

    function createRemoteRepositorySection(activeProject,pane) {
        $('<h3></h3>').text(RED._("sidebar.project.projectSettings.versionControl")).appendTo(pane);

        createLocalBranchListSection(activeProject,pane);

        var repoContainer = $('<div class="red-ui-settings-section"></div>').appendTo(pane);
        var title = $('<h4></h4>').text(RED._("sidebar.project.projectSettings.gitRemotes")).appendTo(repoContainer);

        var editRepoButton = $('<button class="red-ui-button red-ui-button-small" style="float: right; margin-right: 10px;">' + RED._("sidebar.project.projectSettings.addRemote") + '</button>')
            .appendTo(title)
            .on("click", function(evt) {
                editRepoButton.attr('disabled',true);
                addRemoteDialog.slideDown(200, function() {
                    addRemoteDialog[0].scrollIntoView();
                    if (isEmpty) {
                        remoteNameInput.val('origin');
                        remoteURLInput.trigger("focus");
                    } else {
                        remoteNameInput.trigger("focus");
                    }
                    validateForm();
                });
            });


        var emptyItem = { empty: true };
        var isEmpty = true;
        var row = $('<div class="red-ui-settings-row"></div>').appendTo(repoContainer);
        var addRemoteDialog = $('<div class="red-ui-projects-dialog-list-dialog"></div>').hide().appendTo(row);
        row = $('<div class="red-ui-settings-row red-ui-projects-dialog-list"></div>').appendTo(repoContainer);
        var remotesList = $('<ol>').appendTo(row);
        remotesList.editableList({
            addButton: false,
            height: 'auto',
            addItem: function(row,index,entry) {

                var container = $('<div class="red-ui-projects-dialog-list-entry">').appendTo(row);
                if (entry.empty) {
                    container.addClass('red-ui-search-empty');
                    container.text(RED._("sidebar.project.projectSettings.noRemotes"));
                    return;
                } else {
                    $('<span class="entry-icon"><i class="fa fa-globe"></i></span>').appendTo(container);
                    var content = $('<span>').appendTo(container);
                    $('<div class="entry-name">').text(entry.name).appendTo(content);
                    if (entry.urls.fetch === entry.urls.push) {
                        $('<div class="entry-detail">').text(entry.urls.fetch).appendTo(content);
                    } else {
                        $('<div class="entry-detail">').text("fetch: "+entry.urls.fetch).appendTo(content);
                        $('<div class="entry-detail">').text("push: "+entry.urls.push).appendTo(content);

                    }
                    var tools = $('<span class="entry-tools">').appendTo(container);
                    $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-trash"></i></button>')
                        .appendTo(tools)
                        .on("click", function(e) {
                            e.preventDefault();
                            var spinner = utils.addSpinnerOverlay(row).addClass('red-ui-component-spinner-contain');
                            var notification = RED.notify(RED._("sidebar.project.projectSettings.deleteRemoteConfrim", { name: entry.name }), {
                                type: "warning",
                                modal: true,
                                fixed: true,
                                buttons: [
                                    {
                                        text: RED._("common.label.cancel"),
                                        click: function() {
                                            spinner.remove();
                                            notification.close();
                                        }
                                    },{
                                        text: RED._("sidebar.project.projectSettings.deleteRemote"),
                                        click: function() {
                                            notification.close();

                                            if (activeProject.git.branches.remote && activeProject.git.branches.remote.indexOf(entry.name+"/") === 0) {
                                                delete activeProject.git.branches.remote;
                                            }
                                            if (activeProject.git.branches.remoteAlt && activeProject.git.branches.remoteAlt.indexOf(entry.name+"/") === 0) {
                                                delete activeProject.git.branches.remoteAlt;
                                            }

                                            var url = "projects/"+activeProject.name+"/remotes/"+entry.name;
                                            var options = {
                                                url: url,
                                                type: "DELETE",
                                                responses: {
                                                    200: function(data) {
                                                        row.fadeOut(200,function() {
                                                            remotesList.editableList('removeItem',entry);
                                                            setTimeout(spinner.remove, 100);
                                                            if (data.remotes.length === 0) {
                                                                delete activeProject.git.remotes;
                                                                isEmpty = true;
                                                                remotesList.editableList('addItem',emptyItem);
                                                            } else {
                                                                activeProject.git.remotes = {};
                                                                data.remotes.forEach(function(remote) {
                                                                    var name = remote.name;
                                                                    delete remote.name;
                                                                    activeProject.git.remotes[name] = remote;
                                                                });
                                                            }
                                                            delete activeProject.git.branches.remoteAlt;
                                                            RED.sidebar.versionControl.refresh();
                                                        });
                                                    },
                                                    400: {
                                                        '*': function(error) {
                                                            utils.reportUnexpectedError(error);
                                                            spinner.remove();
                                                        }
                                                    },
                                                }
                                            }
                                            utils.sendRequest(options);
                                        }
                                    }

                                ]
                            })
                        });
                }


            }
        });

        var validateForm = function() {
            var validName = /^[a-zA-Z0-9\-_]+$/.test(remoteNameInput.val());
            var repo = remoteURLInput.val();
            // var validRepo = /^(?:file|git|ssh|https?|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?[\w\.@:\/~_-]+(?:\.git)?(?:\/?|\#[\d\w\.\-_]+?)$/.test(remoteURLInput.val());
            var validRepo = repo.length > 0 && !/\s/.test(repo);
            if (/^https?:\/\/[^/]+@/i.test(repo)) {
                remoteURLLabel.text(RED._("sidebar.project.projectSettings.urlRule2"));
                validRepo = false;
            } else {
                remoteURLLabel.text(RED._("sidebar.project.projectSettings.urlRule"));
            }
            saveButton.attr('disabled',(!validName || !validRepo))
            remoteNameInput.toggleClass('input-error',remoteNameInputChanged&&!validName);
            remoteURLInput.toggleClass('input-error',remoteURLInputChanged&&!validRepo);
            if (popover) {
                popover.close();
                popover = null;
            }
        };
        var popover;
        var remoteNameInputChanged = false;
        var remoteURLInputChanged = false;

        $('<div class="red-ui-projects-dialog-list-dialog-header">').text(RED._('sidebar.project.projectSettings.addRemote2')).appendTo(addRemoteDialog);

        row = $('<div class="red-ui-settings-row"></div>').appendTo(addRemoteDialog);
        $('<label for=""></label>').text(RED._("sidebar.project.projectSettings.remoteName")).appendTo(row);
        var remoteNameInput = $('<input type="text">').appendTo(row).on("change keyup paste",function() {
            remoteNameInputChanged = true;
            validateForm();
        });
        $('<label class="red-ui-projects-edit-form-sublabel"><small>' + RED._("sidebar.project.projectSettings.nameRule") + '</small></label>').appendTo(row).find("small");
        row = $('<div class="red-ui-settings-row"></div>').appendTo(addRemoteDialog);
        $('<label for=""></label>').text(RED._("sidebar.project.projectSettings.url")).appendTo(row);
        var remoteURLInput = $('<input type="text">').appendTo(row).on("change keyup paste",function() {
            remoteURLInputChanged = true;
            validateForm()
        });
        var remoteURLLabel = $('<label class="red-ui-projects-edit-form-sublabel"><small>' + RED._("sidebar.project.projectSettings.urlRule") +'</small></label>').appendTo(row).find("small");

        var hideEditForm = function() {
            editRepoButton.attr('disabled',false);
            addRemoteDialog.hide();
            remoteNameInput.val("");
            remoteURLInput.val("");
            if (popover) {
                popover.close();
                popover = null;
            }
        }
        var formButtons = $('<span class="button-row" style="position: relative; float: right; margin: 10px;"></span>')
            .appendTo(addRemoteDialog);
        $('<button class="red-ui-button">' + RED._("common.label.cancel") + '</button>')
            .appendTo(formButtons)
            .on("click", function(evt) {
                evt.preventDefault();
                hideEditForm();
            });
        var saveButton = $('<button class="red-ui-button">' + RED._("sidebar.project.projectSettings.addRemote2") + '</button>')
            .appendTo(formButtons)
            .on("click", function(evt) {
                evt.preventDefault();
                var spinner = utils.addSpinnerOverlay(addRemoteDialog).addClass('red-ui-component-spinner-contain');

                var payload = {
                    name: remoteNameInput.val(),
                    url: remoteURLInput.val()
                }
                var done = function(err) {
                    spinner.remove();
                    if (err) {
                        return;
                    }
                    hideEditForm();
                }
                // console.log(JSON.stringify(payload,null,4));
                RED.deploy.setDeployInflight(true);
                utils.sendRequest({
                    url: "projects/"+activeProject.name+"/remotes",
                    type: "POST",
                    responses: {
                        0: function(error) {
                            done(error);
                        },
                        200: function(data) {
                            activeProject.git.remotes = {};
                            data.remotes.forEach(function(remote) {
                                var name = remote.name;
                                delete remote.name;
                                activeProject.git.remotes[name] = remote;
                            });
                            updateForm();
                            RED.sidebar.versionControl.refresh();
                            done();
                        },
                        400: {
                            'git_remote_already_exists': function(error) {
                                popover = RED.popover.create({
                                    target: remoteNameInput,
                                    direction: 'right',
                                    size: 'small',
                                    content: "Remote already exists",
                                    autoClose: 6000
                                }).open();
                                remoteNameInput.addClass('input-error');
                                done(error);
                            },
                            '*': function(error) {
                                utils.reportUnexpectedError(error);
                                done(error);
                            }
                        },
                    }
                },payload);
            });

        var updateForm = function() {
            remotesList.editableList('empty');
            var count = 0;
            if (activeProject.git.hasOwnProperty('remotes')) {
                for (var name in activeProject.git.remotes) {
                    if (activeProject.git.remotes.hasOwnProperty(name)) {
                        count++;
                        remotesList.editableList('addItem',{name:name,urls:activeProject.git.remotes[name]});
                    }
                }
            }
            isEmpty = (count === 0);
            if (isEmpty) {
                remotesList.editableList('addItem',emptyItem);
            }
        }
        updateForm();
    }

    function createSettingsPane(activeProject) {
        var pane = $('<div id="red-ui-project-settings-tab-settings" class="red-ui-project-settings-tab-pane red-ui-help"></div>');
        createFilesSection(activeProject,pane);
        // createLocalRepositorySection(activeProject,pane);
        createRemoteRepositorySection(activeProject,pane);
        return pane;
    }

    function refreshModuleInUseCounts() {
        modulesInUse = {};
        RED.nodes.eachNode(_updateModulesInUse);
        RED.nodes.eachConfig(_updateModulesInUse);
    }

    function _updateModulesInUse(n) {
        if (!/^subflow:/.test(n.type)) {
            var module = RED.nodes.registry.getNodeSetForType(n.type).module;
            if (module !== 'node-red') {
                if (!modulesInUse.hasOwnProperty(module)) {
                    modulesInUse[module] = {
                        module: module,
                        version: RED.nodes.registry.getModule(module).version,
                        count: 0,
                        known: false
                    }
                }
                modulesInUse[module].count++;
            }
        }
    }

    var popover;
    var utils;
    var modulesInUse = {};
    function init(_utils) {
        utils = _utils;
        addPane({
            id:'main',
            title: RED._("sidebar.project.name"),
            get: createMainPane,
            close: function() { }
        });
        addPane({
            id:'deps',
            title: RED._("sidebar.project.dependencies"),
            get: createDependenciesPane,
            close: function() { }
        });
        addPane({
            id:'settings',
            title: RED._("sidebar.project.settings"),
            get: createSettingsPane,
            close: function() {
                if (popover) {
                    popover.close();
                    popover = null;
                }
            }
        });

        RED.events.on('nodes:add', _updateModulesInUse);
        RED.events.on('nodes:remove', function(n) {
            if (!/^subflow:/.test(n.type)) {
                var module = RED.nodes.registry.getNodeSetForType(n.type).module;
                if (module !== 'node-red' && modulesInUse.hasOwnProperty(module)) {
                    modulesInUse[module].count--;
                    if (modulesInUse[module].count === 0) {
                        if (!modulesInUse[module].known) {
                            delete modulesInUse[module];
                        }
                    }
                }
            }
        })



    }
    return {
        init: init,
        show: show,
        switchProject: function(name) {
            // TODO: not ideal way to trigger this; should there be an editor-wide event?
            modulesInUse = {};
        }
    };
})();
