fcf.module({
  name: "fcfControls:templates/form.wrapper.js",
  dependencies: ["fcf:NClient/Wrapper.js"],
  module: function(Wrapper){
    return class FormWrapper extends Wrapper{
      
      constructor(a_initializeOptions){
        super(a_initializeOptions);
      }

      initialize() {
        let self = this;
        return super.initialize()
        .then(()=>{
          return fcf.loadFilters(self.getArg("fields"));
        })
      }

      processWritenValue(a_valuesInfo, a_defaultLanguage){
        let subValuesInfo = {};
        for(let lang in a_valuesInfo) {
          for(let key in a_valuesInfo[lang].value) {
            if (!subValuesInfo[key])
              subValuesInfo[key] = {};
            subValuesInfo[key][lang] = {
              value: a_valuesInfo[lang].value[key],
              ignore: false,
            };
          }
        }
        for(let key in subValuesInfo) {
          let child = this.getChild(key);
          if (!child)
            continue;
          child.processWritenValue(subValuesInfo[key], a_defaultLanguage);
        }
        for(let lang in a_valuesInfo)
          delete a_valuesInfo[lang];
        for(let key in subValuesInfo) {
          for(let lang in subValuesInfo[key]) {
            if (subValuesInfo[key][lang].ignore)
              continue;
            if (!a_valuesInfo[lang]){
              a_valuesInfo[lang] = {
                value: {}, 
                ignore: false
              };
            }
            a_valuesInfo[lang].value[key] = subValuesInfo[key][lang].value;
          }

        }
      }

      onArg(a_argName, a_value, a_editor, a_innerCall, a_suffix) {
        if (!this.isChild(a_editor) && !a_innerCall)
          this.update();
      }

      getValidateErrorString(a_errors) {
        if (fcf.empty(a_errors))
          return "";
        let message = "<div><errorheader>" + fcf.t("Invalid form fields") + ":</errorheader></div>";        
        fcf.each(a_errors, (a_key, a_errorInfo)=>{
          let view = fcf.getWrapper(a_errorInfo.id).getArg("view")
          let title = view && view.title ? view.title : a_errorInfo.alias;
          message += "<div><erroritem>" + fcf.t("Field") + " '" + fcf.t(title) + "': " + a_errorInfo.error.message + "</erroritem></div>";
        })
        return message;
      }

      validate(a_value, a_info, a_errors) {
        if (typeof a_value !== "object")
          return;
        let result = [];
        let childs = this.getChilds();
        let mode   = this.getArg("mode");
        fcf.each(childs, function(k, child){
          let view = child.getArgs();
          if (!view)
            return;
          if (mode.indexOf("add") == 0 && view.notAdd)
            return;
          if (mode.indexOf("edit") == 0 && view.notEdit)
            return;
          let alias = child.getAlias();
          fcf.append(result, child.validate(typeof a_value === "object" ? a_value[alias] : undefined, a_info, a_errors));
        });
        return result;
      }

      onArgErrors(a_errors){
        fcf.each(this._lastErrors, (a_key, a_error)=>{
          let form = this._getFormById(a_error.id);
          if (form)
            form.setArg("errors", [], true);
        });
        this._lastErrors = [];
        let errorsMap = {};
        fcf.each(a_errors, (a_key, a_error)=>{
          let form = this._getFormById(a_error.id);
          if (!form)
            return;
          if (!errorsMap[form.getId()])
            errorsMap[form.getId()] = [];
          errorsMap[form.getId()].push(a_error);
          this._lastErrors.push(a_error);
        });
        fcf.each(errorsMap, (a_key, a_subErrors)=>{
          let form = this._getFormById(fcf.first(a_subErrors).id);
          form.setArg("errors", a_subErrors, true);
        });
        let selfErrors = fcf.append(true, [], a_errors);
        fcf.each(selfErrors, (a_key, a_error) => {
          let form = this._getFormById(a_error.id);
          if (form) {
            a_error.realAlias = a_error.alias;
            delete a_error.alias;
          }
        });
        this.setArg("errors", selfErrors, true);
        this.update();
      }

      _getFormById(a_id){
        let wrapper = fcf.getWrapper(a_id);
        while (wrapper) {
          if (wrapper == this)
            return;
          if (wrapper instanceof FormWrapper)
            return wrapper;
          wrapper = wrapper.getParent();
        };
      }

    };
  }
});
