fcf.module({
  name: "fcfControls:templates/form.hooks.js",
  dependencies: [],
  module: function(){
    return {
      //
      // void hookBeforeBuild(a_taskInfo)
      // The hook is executed before assembling the template arguments
      //
      // hookBeforeBuild: function(a_taskInfo) {
      // },

      //
      // void hookAfterBuild(a_taskInfo)
      // The hook is executed after assembling the template arguments
      //
      // hookAfterBuild: function(a_taskInfo) {
      // },

      //
      // void hookAfterBuild(a_taskInfo)
      // The hook is executed after building the template's system arguments
      //
      // hookAfterSystemBuild: function(a_taskInfo) {
      // },

      //
      // Object of hooks for programmatically populated arguments
      //
      hooksProgrammableArgument: {
        fields: (a_taskInfo)=>{
          return a_taskInfo.args.fields ? a_taskInfo.args.fields : [];
        },
        errorsMap: (a_taskInfo)=>{
          let errorsMap = {};
          fcf.each(a_taskInfo.args.errors, (k, errorInfo)=>{
            if (!errorInfo.alias)
              return;
            if (!errorsMap[errorInfo.alias])
              errorsMap[errorInfo.alias] = [];
            errorsMap[errorInfo.alias].push(errorInfo.error);
          })
          return errorsMap;
        },
        fieldsMap: (a_taskInfo)=>{
          return fcf.map(a_taskInfo.args.fields, function(k,v){ return [v.alias, v];});
        }
      },

      //
      // Object of the hooks preprocessing of the template arguments
      //
      // hooksBeforeArgument: {
      //   // 
      //   // @result Can return the value of an argument or Promise or undefined
      //   //
      //   "ARG_NAME": function(a_taskInfo) {
      //   }
      // },

      //
      // Object of the hooks postprocessing of the template arguments
      //
      hooksAfterArgument: {
        //
        // @result Can return the value of an argument or Promise or undefined
        //
        "fields": function(a_taskInfo) {
          let fields = typeof a_taskInfo.args.fields === "object" ? a_taskInfo.args.fields : [];
          let newFields = [];
          fcf.each(fields, (k, field)=>{
            field = fcf.buildView(field, a_taskInfo.args.mode);

            if (field.inner)
              return;
            if (!field.args)
              field.args = {};
            if (!field.args.width && a_taskInfo.args.fieldsWidth)
              field.args.width = a_taskInfo.args.fieldsWidth;
            field.args.fcfAlias = field.alias;

            if ("args" in field && "value" in field.args){
              a_taskInfo.args.value[field.alias] = field.args.value;
              delete field.args.value;
            }

            if ("value" in field){
              a_taskInfo.args.value[field.alias] = field.value;
              delete field.value;
            }

            newFields.push(field);
          });

          // remove fields
          let resultFields = [];
          let modPart = a_taskInfo.args.mode.split(".")[0];
          fcf.each(newFields, (a_key, a_field)=>{
            if ( !(modPart === "edit" && a_field.notEdit)  &&
                 !(modPart === "add" && a_field.notAdd) ){
              resultFields.push(a_field);
            }
          })

          a_taskInfo.args.fields = fcf.pattern(resultFields, {record: a_taskInfo.args.value});
          a_taskInfo.args.fields = fcf.tokenize(a_taskInfo.args.fields, {record: a_taskInfo.args.value});
        }
      },
    };
  }
});
