fcf.module({
  name: "fcf:NFSQL/NDetails/AutomateUpdate.js",
  dependencies: ["fcf:NFSQL/NDetails/AutomateSingleField.js", "fcf:NFSQL/NDetails/AutomateSingleValue.js", "fcf:NFSQL/NDetails/AutomateWhere.js", "fcf:NFSQL/NDetails/AutomateLanguageItem.js"],
  module: function(AutomateSingleField, AutomateSingleValue) {
    var Automate = fcf.prepareObject(fcf, "NFSQL.NDetails.Automate");


    Automate.StepUpdate = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map[""] = {factory: "StepSingleField", exit: "StepUpdate_WaitSet", dstValue: "from", skipFirst: false};

      this.actionSwitch = function() {
        this.state.join = [];
        this.state.details.update = {
          field: undefined,
          value: undefined,
        };
      }
    }

    Automate.StepUpdate_WaitSet = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map["^{nm}"] = {factory: "StepUpdate_ReadSet", skipFirst: false};
    }

    Automate.StepUpdate_ReadSet = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{nm}"] = null;
      this.map["^{nnm}"] = {map: {
          "set":  {factory: "StepUpdate_ReadField", skipFirst: false},
          "left": {factory: "StepUpdate_ReadLeftJoinSkipSpaces", skipFirst: false},
          "right": {factory: "StepUpdate_ReadRightJoinSkipSpaces", skipFirst: false},
          "join": {factory: "StepUpdate_ReadJoinSimple", skipFirst: false},
        },
      }
    };

    Automate.StepUpdate_ReadLeftJoinSkipSpaces = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map[""] = {factory: "StepUpdate_ReadJoin", skipFirst: false};
      this.actionSwitch = function() {
        this.state.join.push({
          join: "left",
        });
      }
    }

    Automate.StepUpdate_ReadRightJoinSkipSpaces = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map[""] = {factory: "StepUpdate_ReadJoin", skipFirst: false};
      this.actionSwitch = function() {
        this.state.join.push({
          join: "right",
        });
      }
    }

    Automate.StepUpdate_ReadJoinSimple = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map[""] = {factory: "StepUpdate_Join_ReadTableSkipSpaces", skipFirst: false};
      this.actionSwitch = function() {
        this.state.join.push({
          join: "left",
        });
      }
    }

    Automate.StepUpdate_ReadJoin = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{nm}"] = null;
      this.map["^{nnm}"] = {map:
        { "join": {factory: "StepUpdate_Join_ReadTableSkipSpaces", skipFirst: false} },
      };
    }

    Automate.StepUpdate_Join_ReadTableSkipSpaces = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map["^{nm}"] = {factory: "StepUpdate_Join_ReadTable", skipFirst: false};
      this.map["\""]    = {factory: "StepUpdate_Join_ReadTableQuote", skipFirst: true};
    }

    Automate.StepUpdate_Join_ReadTable = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{nm}"] = null;
      this.map["^{nnm}"] = {factory: "StepUpdate_Join_WaitCommand", skipFirst: false};
      this.actionSwitch = function() {
        fcf.last(this.state.join).from = this.buffer;
      }
    }

    Automate.StepUpdate_Join_ReadTableQuote = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map[""] = null;
      this.map["\""] = {factory: "StepUpdate_Join_WaitCommand", skipFirst: true};
      this.actionSwitch = function() {
        fcf.last(this.state.join).from = this.buffer;
      }
    }


    Automate.StepUpdate_Join_WaitCommand = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map["^{nm}"] = {factory: "StepUpdate_Join_ReadCommand", skipFirst: false};
    }

    Automate.StepUpdate_Join_ReadCommand = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{nm}"] = null;
      this.map["^{nnm}"] = {
        map: {
          "as": {factory: "StepUpdate_Join_ReadAsSkipSpaces", skipFirst: false},
          "on": { factory: "StepUpdate_Join_On",              skipFirst: false }
        },
      };
    }

    Automate.StepUpdate_Join_On = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map[""] = {  factory: "StepWhere",
                        skipFirst: false,
                        exitMap: {
                          "set" :   { factory: Automate.StepUpdate_ReadSet, name:  "StepUpdate_ReadSet", skipFirst: false, attachBuffer: true},
                          "left" :  { factory: Automate.StepUpdate_ReadSet, name:  "StepUpdate_ReadSet", skipFirst: false, attachBuffer: true},
                          "right" : { factory: Automate.StepUpdate_ReadSet, name:  "StepUpdate_ReadSet", skipFirst: false, attachBuffer: true},
                          "join" :  { factory: Automate.StepUpdate_ReadSet, name:  "StepUpdate_ReadSet", skipFirst: false, attachBuffer: true}
                        },
                      }
      this.actionSwitch = function() {
        var join = this.state.join[this.state.join.length-1];
        join.on = [];
        a_state.details.whereContainer = join.on;
        a_state.details.wherePath = `join[${this.state.join.length-1}].on`;
      }
    };

    Automate.StepUpdate_Join_ReadAsSkipSpaces = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map["^{nm}"] = {factory: "StepUpdate_Join_ReadAs", skipFirst: false};
      this.map["\""] = {factory: "StepUpdate_Join_ReadAsQuotes", skipFirst: true};
    }

    Automate.StepUpdate_Join_ReadAs = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{nm}"] = null;
      this.map["^{nnm}"] = {factory: "StepUpdate_Join_WaitCommand", skipFirst: false};
      this.actionSwitch = function() {
        fcf.last(this.state.join).as = this.buffer;
      }
    }

    Automate.StepUpdate_Join_ReadAsQuotes = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map[""] = null;
      this.map["\""] = {factory: "StepUpdate_Join_WaitCommand", skipFirst: true};
      this.actionSwitch = function() {
        fcf.last(this.state.join).as = this.buffer;
      }
    }

    Automate.StepUpdate_ReadField = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.state.details.update.fields = [];
      this.map["${s}"] = null;
      this.map[""] = {  factory:     "StepFieldEx",
                        skipFirst:   false,
                        attachBuffer:true,
                        enableAs:    false,
                        enableList:  false,
                        enableAll:   false,
                        enableArgs:  false,
                        fields:      this.state.details.update.fields,
                        path:        `fields[${this.state.details.update.fields.length}]`,
                        exitMap: {
                          "": { factory: "StepUpdate_WaitEqual", skipFirst: false}
                        }
                     };

    }

    Automate.StepUpdate_WaitEqual = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map["="] = { factory: "StepSingleValue", exit: "StepUpdate_WaitNextValue", dstValue: "details.update.value", skipFirst: true, path: `values[${this.state.values.length}].value`};
    }

    Automate.StepUpdate_WaitNextValue = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map[","]     = {factory: "StepUpdate_ReadField", skipFirst: true};
      this.map["^{nm}"] = {factory: "StepUpdate_WaitWhere", skipFirst: false};
      this.actionSwitch = function() {
        this.state.values.push(fcf.append(this.state.details.update.fields[0], this.state.details.update.value));
      }
    }

    Automate.StepUpdate_WaitWhere = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{nm}"] = null;
      this.map["^{nnm}"] = {map:{ "where": {factory: "StepWhere", skipFirst: false},
                                  "language": {factory: "LanguageItem_SkipSpaces", skipFirst: false},
                                }};
      this.state.details.whereContainer = this.state.where;
      this.state.details.wherePath = "where";
    }

    return Automate;
  }
});
