fcf.module({
  name: "fcfDBControls:templates/table.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) {
      // },

      hooksProgramableArgument: {
        "value": function(a_taskInfo){
          let mode        = a_taskInfo.args.mode;
          let shortMode   = fcf.cutMode(a_taskInfo.args.mode, 2);
          let dbfileds    = [];
          let projection  = fcf.getProjection(a_taskInfo.args.projection)

          if (shortMode == "read.min"){
            dbfileds.push({function: "key", as: "@key"});
            dbfileds.push({function: "title", as: "@title"});
            dbfileds.push({function: "description", as: "@description"});
          } else {
            dbfileds = fcf.array(projection.fields, (a_k, a_filed) => {
              let view = fcf.buildView(a_filed, mode);
              return view.hidden ? undefined : {field: view.alias, as: view.alias};
            })
            dbfileds.push({function: "key", as: "@key"});
            dbfileds.push({function: "title", as: "@title"});
          }

          let where = [];
          if (!fcf.empty(a_taskInfo.search)){
            let searchWhere = [];
            let likeString  = "%" + a_taskInfo.search + "%";
            fcf.each(dbfileds, (k, field) => {
              if (!field.function && !fcf.getFilter(field).availableComparison("like"))
                return;
              searchWhere.push({logic: "or", type: "like", args: [{field: field.alias}, {value: likeString}]})
            })
            where.push({logic: "and", type: "block", args: searchWhere});
          }

          return fcf.application.getStorage().query({
            query: {
              type: "select",
              from: a_taskInfo.args.projection,
              fields: dbfileds,
              where: where,
            },
            context: fcf.getContext(),
          })
          .then(function(a_data){
            return a_data[0]
          });
        },
        "columns": function(a_taskInfo){
          let columns = [];
          let shortMode   = fcf.cutMode(a_taskInfo.args.mode, 2);
          if (shortMode == "read.min" && !Array.isArray(a_taskInfo.args.columns)){
            columns.push({
              alias: "@key",
              type:  "int",
              title: fcf.t("Id"),
            });
            columns.push({
              alias: "@title",
              type:  "text",
              title: fcf.t("Title"),
            });
            columns.push({
              alias: "@description",
              type:  "text",
              title: fcf.t("Description"),
            });
          } else {
            columns = fcf.clone(fcf.getProjection(a_taskInfo.args.projection).fields);
            if (shortMode == "read.short")
              fcf.each(columns, (k, c) => {c.cutHTML = true; c.cutSize = 1024; });
          }

          let result = columns;

          if (Array.isArray(a_taskInfo.args.columns)){
            result = [];
            fcf.each(a_taskInfo.args.columns, (a_key, a_column)=>{
              if (typeof a_column == "string"){
                let srcColumn = columns[fcf.find(columns, (k, v)=>{ return v.alias == a_column})];
                if (srcColumn){
                  result.push(srcColumn);
                } else {
                  result.push({
                    alias: a_column,
                    field: a_column,
                    title: a_column,
                    type:  "text",
                  });
                }
              } else {
                let srcColumn = columns[fcf.find(columns, (k, v)=>{ return v.alias == a_column.alias})];
                result.push(fcf.append({}, srcColumn, a_column));
              }
            });
          }

          let withoutInner = [];
          fcf.each(result, (k, v)=>{
            if (v.inner)
              return;
            withoutInner.push(v);
          })


          return withoutInner;
        }
      },

      hooksBeforeArgument: {
        "value": function(a_taskInfo) {
          return fcf.loadFilters(a_taskInfo.args.columns);
        }
      },

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