if (fcf.isServer())
  var fs = require('fs');

fcf.addException("ERROR_PACKAGE_NOT_FOUND", "Theme ${{theme}}$ not found");

fcf.module({
  name: "fcf:NTheme/Themes.js",
  dependencies: ["fcf:NTheme/Theme.js"],
  module: function(Theme) {
    var NRender = fcf.prepareObject(fcf, "NRender");

    NRender.Themes = function(a_initializeOptions) {
      /**
      * @fn void constructor(a_initializeOptions)
      * @param object a_initializeOptions
      *         - array             sources
      *         - string            defaultTheme
      *         - object            configuration
      **/

      var self = this;
      this._themes = {};
      this._aliases = {};
      this._views = {};
      this._defaultTheme = a_initializeOptions.defaultTheme ? a_initializeOptions.defaultTheme : "defaultTheme";

      this.getTheme = function(a_name, a_safeMode) {
        var result = fcf.empty(a_name) || a_name === "default"  ? this._themes[this._defaultTheme] :
                     this._themes[a_name]                       ? this._themes[a_name] :
                     a_safeMode                                 ? this._themes[this._defaultTheme] :
                                                                  undefined;
        var name = a_name ? a_name : this._defaultTheme;
        if (!result && !a_safeMode)
          throw new fcf.Exception("ERROR_PACKAGE_NOT_FOUND", {theme: name});
        return result;
      }


      this.getThemes = function(){
        return this._themes;
      }

      this.getDefaultThemeName = function(){
        return this._defaultTheme;
      }

      this.getDefaultTheme = function(){
        return this._themes[this._defaultTheme];
      }

      this.setDefaultThemeName = function(a_defaultThemeName){
        this._defaultTheme = a_defaultThemeName;
      }

      this.attachTheme = function(a_name, a_theme){
        this._themes[a_name] = a_theme;
      }

      this.initialize = function() {
        var themes = undefined;
        var actions = fcf.actions();
        return actions
        .then(function(a_res, a_act){
          self._findThemes(function(a_error, a_themes) {
            if (a_error) {
              a_act.error(a_error);
              return;
            }
            themes = a_themes;
            a_act.complete();
          });
        })
        .each(function(){return themes;}, function(a_key, a_themeName, a_res, a_act){
          var theme = new Theme({
            package:        a_themeName,
            sources:        a_initializeOptions.sources,
            configuration:  a_initializeOptions.configuration,
          });
          self._themes[a_themeName]= theme;
          fcf.actions()
          .then(()=>{
            return theme.initialize();
          })
          .then(function(){
            a_act.complete();
          })
          .catch(function(a_error){
            a_act.error(a_error)
          })
        })
        .then(function(){
          for(var key in self._themes){
            self._themes[key].setAliases(self._aliases);
            self._themes[key].setViews(self._views);
          }
        });
      }

      this.setAliases = function(a_aliases) {
        for (var key in this._themes)
          this._themes[key].setAliases(a_aliases);
        fcf.append(this._aliases, a_aliases);
      }

      this.getAliases = function() {
        return this._aliases;
      }

      this.setViews = function(a_views) {
        for (var key in this._themes)
          this._themes[key].setViews(a_views);
        for(var key in a_views){
          if (!this._views[key])
            this._views[key] =  {};
          fcf.append(this._views[key], a_views[key]);
        }
      }

      this._findThemes = function(a_cb) {
        var themes = [];
        var actions = fcf.actions();

        function clReadDir(a_path) {
          a_path = fcf.getPath(a_path);
          return fcf.actions().then(function(a_res, a_act) {

            fs.readdir(a_path, function(a_error, a_items) {
              if (a_error)
                throw new fcf.Exception("ERROR_TEST_OPEN_DIRECTORY", {directory: a_path});
              return fcf.actions().each(a_items, function(a_key, a_item, a_res) {
                var pathFile = a_path + "/" + a_item;
                if (fs.lstatSync(pathFile).isFile()) {
                  var fileExtension = fcf.getExtension(pathFile);
                  if (fileExtension != "theme")
                    return;
                  themes.push(fcf.getShortFileName(pathFile));
                } else {
                  return clReadDir(pathFile);
                }
              })
              .then(()=>{
                a_act.complete();
              })
            });

          });
        };

        actions.each(a_initializeOptions.sources, (a_key, a_value)=>{
          return clReadDir(a_value);
        });

        actions.then(()=>{
          a_cb(undefined, themes);
        });

        actions.catch((a_error)=>{
          a_cb(a_error);
        });
      }
    }

    return NRender.Themes;
  }
});
