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

    function setValue(a_state, a_value) {
      var ptr = fcf.resolveEx(a_state, a_state.details.singleValue.dstValue);
      if (Array.isArray(ptr.object[ptr.key]))
        ptr.object[ptr.key].push({value: a_value});
      else
        ptr.object[ptr.key] = {value: a_value};
    }

    function getValue(a_state) {
      var ptr = fcf.resolveEx(a_state, a_state.details.singleValue.dstValue);
      if (Array.isArray(ptr.object[ptr.key]))
        return ptr.object[ptr.key][ptr.object[ptr.key].length - 1].value;
      else
        return ptr.object[ptr.key].value;
    }

    function getValueParent(a_state) {
      var ptr = fcf.resolveEx(a_state, a_state.details.singleValue.dstValue);
      if (Array.isArray(ptr.object[ptr.key]))
        return ptr.object[ptr.key][ptr.object[ptr.key].length - 1];
      else
        return ptr.object[ptr.key];
    }

    Automate.StepSingleValue = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map["$"] = { factory: "StepSingleValue_Start", skipFirst: true};
      this.actionSwitch = function() {
        this.state.details.singleValue = {
          exit: this.state.details.stepInfo.exit,
          dstValue: this.state.details.stepInfo.dstValue,
          minus: false,
        };
      }
    }

    Automate.StepSingleValue_Start = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["{"] = {factory: "StepSingleValue_Read", skipFirst: true};
      this.map["["] = {factory: "StepSingleValue_Res", skipFirst: true};
    }

    Automate.StepSingleValue_Read = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{nm}"] = null;
      this.map["}"] = {factory: this.state.details.singleValue.exit, skipFirst: true};

      this.actionSwitch = function() {
        var number = parseInt(this.buffer);
        if (isNaN(number))
          throw "Incorrect value";
        var value = this.state.details.args[number-1];
        setValue(this.state, value);
      }
    }

    Automate.StepSingleValue_Res = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map["-"]    = {factory: "StepSingleValue_ResMinus", skipFirst: true};
      this.map[""]     = {factory: "StepSingleValue_ResReadResultSkipSpaces", skipFirst: false};
    }

    Automate.StepSingleValue_ResMinus = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map[""] = {factory: "StepSingleValue_ResReadResultSkipSpaces", skipFirst: false};

      this.actionSwitch = function() {
        this.state.details.singleValue.minus = true;
      }
    }

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

    Automate.StepSingleValue_ResReadResult = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{n}"] = null;
      this.map[""] = {factory: "StepSingleValue_ResResultPostSkipSpaces", skipFirst: false};

      this.actionSwitch = function() {
        var number = parseInt(this.buffer);
        if (isNaN(number))
          throw "Incorrect number";
        if (this.state.details.singleValue.minus)
          number = -number;
        setValue(this.state, {result: number});
      }
    }

    Automate.StepSingleValue_ResResultPostSkipSpaces = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map["]"] = {factory: "StepSingleValue_ResRecordSkipSpaces", skipFirst: true};
    }

    Automate.StepSingleValue_ResRecordSkipSpaces = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map["["] = {factory: "StepSingleValue_ResRecordReadValueSkipSpaces", skipFirst: true};
    }

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

    Automate.StepSingleValue_ResRecordReadValue = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{n}"] = null;
      this.map[""] = {factory: "StepSingleValue_ResRecordClose", skipFirst: false};
      this.actionSwitch = function() {
        var number = parseInt(this.buffer);
        if (isNaN(number))
          throw "Incorrect number";
        var val = getValue(this.state);
        val.record = number;
      }
    }

    Automate.StepSingleValue_ResRecordClose = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map["]"] = {factory: "StepSingleValue_ResItemSkipSpaces", skipFirst: true};
    }

    Automate.StepSingleValue_ResItemSkipSpaces = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map["["] = {factory: "StepSingleValue_ResItemReadSkipSpaces", skipFirst: true};
    }

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

    }

    Automate.StepSingleValue_ResItemReadDQuotes = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map[""] = null;
      this.map["\""] = {factory: "StepSingleValue_ResItemReadClose", skipFirst: true};
      this.actionSwitch = function() {
        var val = getValue(this.state);
        val.item = this.buffer;
      }
    }

    Automate.StepSingleValue_ResItemRead = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{nm}"] = null;
      this.map["^{nnm}"] = {factory: "StepSingleValue_ResItemReadClose", skipFirst: false};
      this.actionSwitch = function() {
        val = getValue(this.state);
        val.item = this.buffer;
        fcf.append(getValueParent(this.state), val);
        delete getValueParent(this.state).value;
      }
    }

    Automate.StepSingleValue_ResItemReadClose = function(a_state) {
      Automate.BaseStep.call(this, a_state);
      this.map["^{s}"] = null;
      this.map["]"] = {factory: this.state.details.singleValue.exit, skipFirst: true};
    }

    return Automate;
  }
});
