fcf.module({
  name: "fcf:NSystem/cache.js",
  dependencies: [],
  module: function(){
    var Namespace = fcf.prepareObject(fcf, "NTools");

    Namespace.Cache = function(){
      var self = this;
      this._cache  = {};
      this._update = {};

      this.append = function(a_part, a_name, a_cbUpdate){
        if (!(a_part in this._update))
          this._update[a_part] = {};
        this._update[a_part][a_name] = { cb: a_cbUpdate }; 
      }

      this.update = function(a_part, a_name) {
        if (!(a_part in this._update))
          return;
        if (!(a_name in this._update[a_part]))
          return;
        var inf = this._update[a_part][a_name];
        var result = inf.cb();

        return fcf.actions()
        .then(()=>{
          return result;
        })
        .then((a_data)=>{
          return fcf.application.getEventChannel().send("cache_update_before", {part: a_part, variable: a_name, value: a_data})
          .then(()=>{
            return a_data;
          });
        })
        .then((a_data)=>{
          if (!(a_part in self._cache))
            self._cache[a_part] = {};
          self._cache[a_part][a_name] = a_data;
          return a_data;
        })
        .then((a_data)=>{
          fcf.application.getEventChannel().send("cache_update_after", {part: a_part, variable: a_name, value: a_data})
          .then(()=>{
          });
        })
      }

      this.updateAll = function(){
        fcf.each(this._update, function(a_partName, a_part){
          fcf.each(a_part, function(a_keyName, a_data){
            self.update(a_partName, a_keyName);
          });
        })
      }

      this.get = function(a_part, a_name){
        if (!(a_part in this._cache))
          return;
        if (!(a_name in this._cache[a_part]))
          return;
        return this._cache[a_part][a_name];
      }

      this.set = function(a_part, a_name, a_data){
        if (!(a_part in this._cache))
          this._cache[a_part] = {};
        this._cache[a_part][a_name] = a_data;
      }

    }

    Namespace.cache = new Namespace.Cache()

    return Namespace.cache;
  }
});
