text: /**
   * 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,
              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>" );
      }
  
      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)) {
                  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) && !modulesInUse.hasOwnProperty(m)) {
                      var installed = !!RED.nodes.registry.getModule(m);
                      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: 'Delete branch',
                                          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 = {};
          }
      };
  })();
  