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.
   **/
  
  var when = require("when");
  var apiUtils = require("../util");
  var redNodes;
  var log;
  var settings;
  
  module.exports = {
      init: function(runtime) {
          redNodes = runtime.nodes;
          log = runtime.log;
          settings = runtime.settings;
      },
      getAll: function(req,res) {
          if (req.get("accept") == "application/json") {
              log.audit({event: "nodes.list.get"},req);
              res.json(redNodes.getNodeList());
          } else {
              var lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
              log.audit({event: "nodes.configs.get"},req);
              res.send(redNodes.getNodeConfigs(lang));
          }
      },
  
      post: function(req,res) {
          if (!settings.available()) {
              log.audit({event: "nodes.install",error:"settings_unavailable"},req);
              res.status(400).json({error:"settings_unavailable", message:"Settings unavailable"});
              return;
          }
          var node = req.body;
          var promise;
          var isUpgrade = false;
          if (node.module) {
              var module = redNodes.getModuleInfo(node.module);
              if (module) {
                  if (!node.version || module.version === node.version) {
                      log.audit({event: "nodes.install",module:node.module, version:node.version, error:"module_already_loaded"},req);
                      res.status(400).json({error:"module_already_loaded", message:"Module already loaded"});
                      return;
                  }
                  if (!module.local) {
                      log.audit({event: "nodes.install",module:node.module, version:node.version, error:"module_not_local"},req);
                      res.status(400).json({error:"module_not_local", message:"Module not locally installed"});
                      return;
                  }
                  isUpgrade = true;
              }
              promise = redNodes.installModule(node.module,node.version);
          } else {
              log.audit({event: "nodes.install",module:node.module,error:"invalid_request"},req);
              res.status(400).json({error:"invalid_request", message:"Invalid request"});
              return;
          }
          promise.then(function(info) {
              if (node.module) {
                  log.audit({event: "nodes.install",module:node.module,version:node.version},req);
                  res.json(info);
              }
          }).catch(function(err) {
              if (err.code === 404) {
                  log.audit({event: "nodes.install",module:node.module,version:node.version,error:"not_found"},req);
                  res.status(404).end();
              } else if (err.code) {
                  log.audit({event: "nodes.install",module:node.module,version:node.version,error:err.code},req);
                  res.status(400).json({error:err.code, message:err.message});
              } else {
                  log.audit({event: "nodes.install",module:node.module,version:node.version,error:err.code||"unexpected_error",message:err.toString()},req);
                  res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
              }
          });
      },
  
      delete: function(req,res) {
          if (!settings.available()) {
              log.audit({event: "nodes.remove",error:"settings_unavailable"},req);
              res.status(400).json({error:"settings_unavailable", message:"Settings unavailable"});
              return;
          }
          var mod = req.params[0];
          try {
              var promise = null;
              var module = redNodes.getModuleInfo(mod);
              if (!module) {
                  log.audit({event: "nodes.remove",module:mod,error:"not_found"},req);
                  res.status(404).end();
                  return;
              } else {
                  promise = redNodes.uninstallModule(mod);
              }
  
              promise.then(function(list) {
                  log.audit({event: "nodes.remove",module:mod},req);
                  res.status(204).end();
              }).catch(function(err) {
                  log.audit({event: "nodes.remove",module:mod,error:err.code||"unexpected_error",message:err.toString()},req);
                  res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
              });
          } catch(err) {
              log.audit({event: "nodes.remove",module:mod,error:err.code||"unexpected_error",message:err.toString()},req);
              res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
          }
      },
  
      getSet: function(req,res) {
          var id = req.params[0] + "/" + req.params[2];
          var result = null;
          if (req.get("accept") === "application/json") {
              result = redNodes.getNodeInfo(id);
              if (result) {
                  log.audit({event: "nodes.info.get",id:id},req);
                  delete result.loaded;
                  res.send(result);
              } else {
                  log.audit({event: "nodes.info.get",id:id,error:"not_found"},req);
                  res.status(404).end();
              }
          } else {
              var lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
              result = redNodes.getNodeConfig(id,lang);
              if (result) {
                  log.audit({event: "nodes.config.get",id:id},req);
                  res.send(result);
              } else {
                  log.audit({event: "nodes.config.get",id:id,error:"not_found"},req);
                  res.status(404).end();
              }
          }
      },
  
      getModule: function(req,res) {
          var module = req.params[0];
          var result = redNodes.getModuleInfo(module);
          if (result) {
              log.audit({event: "nodes.module.get",module:module},req);
              res.json(result);
          } else {
              log.audit({event: "nodes.module.get",module:module,error:"not_found"},req);
              res.status(404).end();
          }
      },
  
      putSet: function(req,res) {
          if (!settings.available()) {
              log.audit({event: "nodes.info.set",error:"settings_unavailable"},req);
              res.status(400).json({error:"settings_unavailable", message:"Settings unavailable"});
              return;
          }
          var body = req.body;
          if (!body.hasOwnProperty("enabled")) {
              log.audit({event: "nodes.info.set",error:"invalid_request"},req);
              res.status(400).json({error:"invalid_request", message:"Invalid request"});
              return;
          }
          var id = req.params[0] + "/" + req.params[2];
          try {
              var node = redNodes.getNodeInfo(id);
              var info;
              if (!node) {
                  log.audit({event: "nodes.info.set",id:id,error:"not_found"},req);
                  res.status(404).end();
              } else {
                  delete node.loaded;
                  putNode(node, body.enabled).then(function(result) {
                      log.audit({event: "nodes.info.set",id:id,enabled:body.enabled},req);
                      res.json(result);
                  });
              }
          } catch(err) {
              log.audit({event: "nodes.info.set",id:id,enabled:body.enabled,error:err.code||"unexpected_error",message:err.toString()},req);
              res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
          }
      },
  
      putModule: function(req,res) {
          if (!settings.available()) {
              log.audit({event: "nodes.module.set",error:"settings_unavailable"},req);
              res.status(400).json({error:"settings_unavailable", message:"Settings unavailable"});
              return;
          }
          var body = req.body;
          if (!body.hasOwnProperty("enabled")) {
              log.audit({event: "nodes.module.set",error:"invalid_request"},req);
              res.status(400).json({error:"invalid_request", message:"Invalid request"});
              return;
          }
          var mod = req.params[0];
          try {
              var module = redNodes.getModuleInfo(mod);
              if (!module) {
                  log.audit({event: "nodes.module.set",module:mod,error:"not_found"},req);
                  return res.status(404).end();
              }
  
              var nodes = module.nodes;
              var promises = [];
              for (var i = 0; i < nodes.length; ++i) {
                  promises.push(putNode(nodes[i],body.enabled));
              }
              when.settle(promises).then(function() {
                  res.json(redNodes.getModuleInfo(mod));
              });
          } catch(err) {
              log.audit({event: "nodes.module.set",module:mod,enabled:body.enabled,error:err.code||"unexpected_error",message:err.toString()},req);
              res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
          }
      },
  
      getIcons: function(req,res) {
          log.audit({event: "nodes.icons.get"},req);
          res.json(redNodes.getNodeIcons());
      }
  };
  
  function putNode(node, enabled) {
      var info;
      var promise;
      if (!node.err && node.enabled === enabled) {
          promise = when.resolve(node);
      } else {
          if (enabled) {
              promise = redNodes.enableNode(node.id);
          } else {
              promise = redNodes.disableNode(node.id);
          }
      }
      return promise;
  }
  