fcf.module({
  name: "fcf:NServer/Configuration.js",
  dependencies: [],
  module: function() {
    var NServer = fcf.prepareObject(fcf, "NServer");

    NServer.Configuration = function() {
      var self = this;

      this._userConfigurations = [];
      this._overwriteConfigurations = [];

      fcf.append(this, {
        restart:                      false,
        port:                         8080,
        controlPort:                  undefined,
        serverControlPort:            undefined,
        host:                         undefined,
        fileСaching:                  true,
        projectionReloadingTimeout:   2000,
        disableWeb:                   false,
        disableSys:                   false,
        disableCron:                  false,
        disableUpdateProjection:      false,
        slave:                        false,
        serverGroup:                  undefined,
        keepAliveTimeout:             5,
        userProjectionName:           "___fcf___users",
        packages:                     [],
        packageDirectories:           ["fcf:packages", "fcf:themes"],
        sessionLifetime:              30,
        sharedUserFileds:             [],
        aliases:                      {},
        views:                        {},
        html:                         { include: {} },
        inheritanceModes:             {},
        filters:                      {},
        functions:                    {},
      });

      this.appendOverwriteConfiguration = function(a_overwriteConfigurations) {
        this._overwriteConfigurations.push(a_overwriteConfigurations);
        this.appendConfiguration({}, false, true);
      }

      this.appendUserConfiguration = function(a_userConfiguration){
        this._userConfigurations.push(a_userConfiguration);
        this.appendConfiguration({}, false, true);
        for(let i = 0; i < this._overwriteConfigurations.length; ++i)
          this._appendConfiguration(this._overwriteConfigurations[i], false, true);
      }

      this.appendConfiguration = function(a_data, a_isTheme){
        this._appendConfiguration(a_data, a_isTheme, false);
      }

      this._appendConfiguration = function(a_data, a_isTheme, a_isUserConfiguration){
        for (let key in a_data) {
          if (key == "packages" && Array.isArray(a_data[key])) {
            fcf.each(a_data[key], (a_key, a_packageName)=>{
              if (fcf.find(this.packages, a_packageName) === undefined)
                this.packages.push(a_packageName);
            })
          } else if (key == "routes" && Array.isArray(a_data[key])) {
            if (fcf.isServer()){
              fcf.application.getRouter().append(a_data[key]);
            }
          } else if (key == "aliases") {
            if (typeof a_data.aliases == "object") {
              fcf.append(this.aliases, a_data.aliases);
            }
          } else if (key == "views") {
            if (typeof a_data.views == "object") {
              for (var mask in a_data.views) {
                if (!(mask in this.views))
                  this.views[mask] = {};
                fcf.append(this.views[mask], a_data.views[mask]);
              }
            }
          } else if (key == "html") {
            if (!a_isTheme) {
              if (typeof a_data.html == "object" && typeof a_data.html.include == "object") {
                fcf.append(this.html.include, a_data.html.include);
              }
            }
          } else if (key == "inheritanceModes") {
            if (typeof a_data.inheritanceModes == "object") {
              fcf.append(this.inheritanceModes, a_data.inheritanceModes);
            }
          } else if (key == "filters") {
            if (typeof a_data.filters == "object") {
              fcf.append(this.filters, a_data.filters);
            }
          } else if (key == "functions") {
            if (typeof a_data.functions == "object") {
              fcf.append(this.functions, a_data.functions);
            }
          } else if (key == "sessionLifetime") {
            if (typeof a_data.sessionLifetime == "number")
              this.sessionLifetime = a_data.sessionLifetime|0;
          } else if (key == "packageDirectories") {
            if (Array.isArray(a_data.packageDirectories)){
              fcf.each(a_data.packageDirectories, (k, packDir)=>{
                if (fcf.find(this.packageDirectories, packDir) === undefined){
                  this.packageDirectories.unshift(packDir);
                }
              })
            }
          } else if (key == "packages") {
            if (typeof a_data.packages == "object") {
              fcf.each(a_data.packages, function(a_key, a_value){
                if (!self.packages)
                  self.packages = {};
                if (!self.packages[a_key])
                  self.packages[a_key] = {};
                fcf.append(self.packages[a_key], a_value);
              });
            }
          } else {
            this[key] = a_data[key];
          }
        }
        if (!a_isUserConfiguration) {
          for(let i = 0; i < this._userConfigurations.length; ++i)
            this._appendConfiguration(this._userConfigurations[i], false, true);
          for(let i = 0; i < this._overwriteConfigurations.length; ++i)
            this._appendConfiguration(this._overwriteConfigurations[i], false, true);
        }

      }


    }


    return NServer.Configuration;
  }
});
