"use strict";

var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) {
  if (k2 === undefined) k2 = k;
  var desc = Object.getOwnPropertyDescriptor(m, k);
  if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
    desc = {
      enumerable: true,
      get: function () {
        return m[k];
      }
    };
  }
  Object.defineProperty(o, k2, desc);
} : function (o, m, k, k2) {
  if (k2 === undefined) k2 = k;
  o[k2] = m[k];
});
var __setModuleDefault = void 0 && (void 0).__setModuleDefault || (Object.create ? function (o, v) {
  Object.defineProperty(o, "default", {
    enumerable: true,
    value: v
  });
} : function (o, v) {
  o["default"] = v;
});
var __importStar = void 0 && (void 0).__importStar || function () {
  var ownKeys = function (o) {
    ownKeys = Object.getOwnPropertyNames || function (o) {
      var ar = [];
      for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
      return ar;
    };
    return ownKeys(o);
  };
  return function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
    __setModuleDefault(result, mod);
    return result;
  };
}();
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
  return mod && mod.__esModule ? mod : {
    "default": mod
  };
};
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.OpenLoopNode = exports.OPENLOOP_VISION_RECOGNITION_SUCCESS_SUFFIX = void 0;
const tree_model_1 = __importDefault(require("tree-model"));
const domain_1 = require("../../domain");
const agv_constant_1 = require("../../entity/agv.constant");
const translation_util_1 = __importStar(require("../../utils/translation.util"));
const scope_setting_1 = require("../../scope-setting");
const webscope_service_1 = require("../../webscope-service");
const TranslationUtil = translation_util_1.default;
exports.OPENLOOP_VISION_RECOGNITION_SUCCESS_SUFFIX = 'Openloop_Vision_Recognition_Success_';
class OpenLoopNode {
  setLinearSpeed(v) {
    this.linearSpeed = v;
    return this;
  }
  getLinearSpeed() {
    return this.linearSpeed;
  }
  setAngularSpeed(w) {
    this.angularSpeed = w;
    return this;
  }
  getAngularSpeed() {
    return this.angularSpeed;
  }
  setVisionEnable(enable) {
    this.visionEnable = enable;
    return this;
  }
  getVisionEnable() {
    return this.visionEnable;
  }
  setVisionResult(result) {
    this.visionResult = result;
    this.pendingVisionResultName = this.extractVariableName(result);
    return this;
  }
  getVisionResult() {
    return this.visionResult;
  }
  setVisionDistance(distance) {
    this.visionDistance = distance;
    return this;
  }
  getVisionDistance() {
    return this.visionDistance;
  }
  setDataModel(dataModel) {
    this.dataModel = dataModel;
    const linearSpeed = dataModel.get(this.OpenLoopLinearSpeedKey, null);
    if (this.isNumber(linearSpeed)) {
      this.linearSpeed = linearSpeed;
    }
    const angularSpeed = dataModel.get(this.OpenLoopAngularSpeedKey, null);
    if (this.isNumber(angularSpeed)) {
      this.angularSpeed = angularSpeed;
    }
    const visionEnable = dataModel.get(this.OpenLoopVisionEnableKey, null);
    if (this.isBoolean(visionEnable)) {
      this.visionEnable = visionEnable;
    }
    const visionResultRaw = dataModel.get(this.OpenLoopVisionResultKey, null);
    const visionResult = visionResultRaw && typeof visionResultRaw === 'object' && 'value' in visionResultRaw ? visionResultRaw.value : visionResultRaw;
    const visionResultIncomingHasDefined = !!(visionResultRaw && typeof visionResultRaw === 'object' && 'hasDefined' in visionResultRaw && visionResultRaw.hasDefined === true);
    if (this.isVariable(visionResult)) {
      this.visionResult = visionResult;
      this.pendingVisionResultName = this.extractVariableName(visionResult);
    } else if (typeof visionResult === 'string' && visionResult) {
      this.pendingVisionResultName = visionResult;
    }
    if (visionResultIncomingHasDefined || !!this.pendingVisionResultName) {
      this.visionResultForcedDefined = true;
    }
    const visionDistance = dataModel.get(this.OpenLoopVisionDistanceKey, null);
    if (this.isNumber(visionDistance)) {
      this.visionDistance = visionDistance;
    }
  }
  getDataModel() {
    const model = this.dataModel;
    model.set(this.OpenLoopLinearSpeedKey, this.linearSpeed, domain_1.XmlLabelType.FLOAT64);
    model.set(this.OpenLoopAngularSpeedKey, this.angularSpeed, domain_1.XmlLabelType.FLOAT64);
    model.set(this.OpenLoopVisionEnableKey, this.visionEnable, domain_1.XmlLabelType.BOOL);
    model.set(this.OpenLoopVisionResultKey, this.visionResult, domain_1.XmlLabelType.VARIABLE);
    model.set(this.OpenLoopVisionDistanceKey, this.visionDistance, domain_1.XmlLabelType.FLOAT64);
    return model;
  }
  isNumber(value) {
    return Number.isFinite(value);
  }
  isBoolean(value) {
    return typeof value === 'boolean';
  }
  isVariable(value) {
    return typeof value === 'object' && value !== null && typeof value.getDisplayName === 'function' && typeof value.getType === 'function';
  }
  extractVariableName(value) {
    if (typeof value === 'string' && value) {
      return value;
    }
    if (!value || typeof value !== 'object') {
      return null;
    }
    const variable = value;
    if (typeof variable.name === 'string' && variable.name) {
      return variable.name;
    }
    if (typeof variable.getDisplayName === 'function') {
      const displayName = variable.getDisplayName();
      if (typeof displayName === 'string' && displayName) {
        return displayName;
      }
    }
    if (typeof variable.getName === 'function') {
      const name = variable.getName();
      if (typeof name === 'string' && name) {
        return name;
      }
    }
    return null;
  }
  toSerializableValue(key, value) {
    if (key === this.OpenLoopVisionResultKey) {
      return this.extractVariableName(value) || this.pendingVisionResultName;
    }
    return value;
  }
  resolveVariableByName(name) {
    if (!name) {
      return null;
    }
    const webscopeService = (0, webscope_service_1.getWebscopeService)();
    if (!webscopeService) {
      return null;
    }
    const variableModel = webscopeService.getVariableModel();
    try {
      const byName = typeof (variableModel === null || variableModel === void 0 ? void 0 : variableModel.getByName) === 'function' ? variableModel.getByName(name) : null;
      if (this.isVariable(byName)) {
        return byName;
      }
    } catch (error) {}
    try {
      const byGet = typeof (variableModel === null || variableModel === void 0 ? void 0 : variableModel.get) === 'function' ? variableModel.get(name) : null;
      if (this.isVariable(byGet)) {
        return byGet;
      }
    } catch (error) {}
    return null;
  }
  getValueFactory() {
    var _a, _b;
    return (_b = (_a = this.programModel).getValueFactory) === null || _b === void 0 ? void 0 : _b.call(_a);
  }
  setId(id) {
    this.id = id;
  }
  update(config) {
    let updated = false;
    for (const key in config) {
      const raw = config[key];
      const value = raw && typeof raw === 'object' && 'value' in raw ? raw.value : raw;
      if (key === this.OpenLoopLinearSpeedKey) {
        if (this.isNumber(Number(value)) && Number(value) !== this.getLinearSpeed()) {
          this.setLinearSpeed(Number(value));
          updated = true;
        }
      } else if (key === this.OpenLoopAngularSpeedKey) {
        if (this.isNumber(Number(value)) && Number(value) !== this.getAngularSpeed()) {
          this.setAngularSpeed(Number(value));
          updated = true;
        }
      } else if (key === this.OpenLoopVisionEnableKey) {
        if (typeof value === 'boolean' && value !== this.getVisionEnable()) {
          this.setVisionEnable(value);
          updated = true;
        }
      } else if (key === this.OpenLoopVisionResultKey) {
        const incomingHasDefined = !!(raw && typeof raw === 'object' && 'hasDefined' in raw && raw.hasDefined === true);
        if (value === null) {
          const hasPending = !!this.pendingVisionResultName;
          if (this.getVisionResult() !== null || hasPending) {
            this.setVisionResult(null);
            this.pendingVisionResultName = null;
            this.visionResultForcedDefined = false;
            updated = true;
          }
        } else {
          const incomingVariableName = this.extractVariableName(value);
          const currentVariableName = this.extractVariableName(this.getVisionResult());
          const lockedVariableName = currentVariableName || this.pendingVisionResultName;
          const variableName = lockedVariableName || incomingVariableName;
          if (variableName === null && value !== null && value !== undefined) {
            continue;
          }
          const hasPendingNameChanged = !lockedVariableName && variableName !== this.pendingVisionResultName;
          if (hasPendingNameChanged) {
            this.pendingVisionResultName = variableName;
          }
          const variable = this.resolveVariableByName(variableName);
          if (!variable && this.getVisionResult() !== null && !!lockedVariableName) {
            continue;
          }
          if (variable !== this.getVisionResult()) {
            this.setVisionResult(variable);
            updated = true;
          }
          if ((incomingHasDefined || !!variableName) && !this.visionResultForcedDefined) {
            this.visionResultForcedDefined = true;
            updated = true;
          }
          if (hasPendingNameChanged) {
            updated = true;
          }
        }
      } else if (key === this.OpenLoopVisionDistanceKey) {
        if (this.isNumber(Number(value)) && Number(value) !== this.getVisionDistance()) {
          this.setVisionDistance(Number(value));
          updated = true;
        }
      }
    }
    return updated;
  }
  dropNode() {}
  toJSON() {
    const result = {};
    const model = this.getDataModel();
    if (!model || typeof model.getKeys !== 'function') {
      return result;
    }
    model.getKeys().forEach(key => {
      const serializedValue = this.toSerializableValue(key, model.get(key, null));
      let hasDefined = !!serializedValue;
      if (key === this.OpenLoopVisionResultKey) {
        hasDefined = this.visionResultForcedDefined || !!serializedValue;
      }
      result[key] = {
        value: serializedValue,
        hasDefined
      };
    });
    return result;
  }
  cloneNode(node) {
    const treeModelInstance = new tree_model_1.default();
    const parseTree = treeModelInstance.parse({});
    const {
      children,
      programNode,
      ...restData
    } = node;
    const nodeData = programNode.getDataModel();
    this.setDataModel(nodeData);
    const currentNode = this.programModel.getProgramTree().addChild(parseTree, node.nodeId, this, 0);
    currentNode.model.disabled = node.disabled;
    currentNode.model.isBreakpoint = node.isBreakpoint;
    currentNode.model.suppressedComment = node.suppressedComment;
    return currentNode;
  }
  constructor(programModel) {
    this.OpenLoopLinearSpeedKey = 'linear_speed';
    this.OpenLoopAngularSpeedKey = 'angular_speed';
    this.OpenLoopVisionEnableKey = 'vision_enable';
    this.OpenLoopVisionResultKey = 'vision_result';
    this.OpenLoopVisionDistanceKey = 'vision_distance';
    this.id = '';
    this.linearSpeed = 0.35;
    this.angularSpeed = 0;
    this.visionEnable = false;
    this.visionResult = null;
    this.pendingVisionResultName = null;
    this.visionResultForcedDefined = false;
    this.visionDistance = 1.0;
    this.programModel = programModel;
    this.node = this;
  }
  generateScript(scriptWriter) {
    var _a, _b, _c, _d;
    const tree_node = (_b = (_a = this.programModel) === null || _a === void 0 ? void 0 : _a.getProgramTree().getTreeNodeById(this.id)) === null || _b === void 0 ? void 0 : _b.model;
    if (!tree_node) {
      return;
    }
    const row = tree_node.lineNumber;
    const valueFactory = (_d = (_c = (0, webscope_service_1.getWebscopeService)()) === null || _c === void 0 ? void 0 : _c.getValueFactory) === null || _d === void 0 ? void 0 : _d.call(_c);
    if (!valueFactory) {
      return;
    }
    const headerFunName = `getHeader_${row}()`;
    const priorityFunName = `setPriority_${row}()`;
    scriptWriter.appendLine(`function ${headerFunName}`);
    scriptWriter.increaseIndent();
    scriptWriter.appendLine(`local map_header = agvc.AgvcInterface.getCurrentMapHeader()`);
    scriptWriter.appendLine(`local header = {`);
    scriptWriter.increaseIndent();
    scriptWriter.appendLine(`id = tostring(socket.gettime() * 1000),`);
    scriptWriter.appendLine(`name = map_header.name,`);
    scriptWriter.appendLine(`map_id = map_header.map_id,`);
    scriptWriter.appendLine(`stamp =  socket.gettime() * 1000`);
    scriptWriter.decreaseIndent();
    scriptWriter.appendLine(`}`);
    scriptWriter.appendLine(`return header`);
    scriptWriter.end();
    scriptWriter.lineFeed();
    scriptWriter.appendLine(`function ${priorityFunName}`);
    scriptWriter.increaseIndent();
    scriptWriter.appendLine(`local priorityParam = { "web", "" }`);
    scriptWriter.appendLine(`local res = agvc.AgvcInterface.setPriority(priorityParam)`);
    const releasePriorityExpression = valueFactory.createExpression();
    releasePriorityExpression.append(`not res or res < 0`);
    scriptWriter.ifCondition(releasePriorityExpression);
    scriptWriter.appendLine(`local release = agvc.AgvcInterface.releasePriority()`);
    scriptWriter.appendLine(`local priority = agvc.AgvcInterface.setPriority(priorityParam)`);
    scriptWriter.appendLine(`textmsg("set priority result:" ..tostring(priority))`);
    scriptWriter.appendLine(`return priority`);
    scriptWriter.end();
    scriptWriter.appendLine(`textmsg("set priority result:" ..tostring(res))`);
    scriptWriter.appendLine(`return res`);
    scriptWriter.end();
    scriptWriter.lineFeed();
    const linear = this.getLinearSpeed();
    const angular = this.getAngularSpeed();
    scriptWriter.appendLine(`local control_speed = {`);
    scriptWriter.increaseIndent();
    scriptWriter.appendLine(`v = ${linear},`);
    scriptWriter.appendLine(`w = ${angular},`);
    scriptWriter.decreaseIndent();
    scriptWriter.appendLine(`}`);
    scriptWriter.lineFeed();
    scriptWriter.appendLine(`${priorityFunName}`);
    scriptWriter.appendLine(`local header = ${headerFunName}`);
    scriptWriter.appendLine(`local param = { header = header, speed = control_speed }`);
    scriptWriter.appendLine(`local result = agvc.AgvcInterface.setControlSpeed(param)`);
    scriptWriter.appendLine(`textmsg("open-loop setControlSpeed result: " .. tostring(result))`);
    scriptWriter.lineFeed();
    const visionEnable = this.getVisionEnable();
    scriptWriter.appendLine(`-- vision obstacle detection enabled: ${visionEnable}`);
    if (visionEnable) {
      const visionDistance = this.getVisionDistance();
      scriptWriter.appendLine(`textmsg("open-loop vision obstacle detection distance: " .. tostring(${visionDistance}))`);
      scriptWriter.appendLine(`local vision_result = agvc.AgvcInterface.isObstacleAhead(${visionDistance})`);
      const visionResultDisplayName = this.extractVariableName(this.getVisionResult());
      if (visionResultDisplayName) {
        scriptWriter.appendLine(`${visionResultDisplayName} = vision_result`);
      }
      scriptWriter.appendLine(`textmsg("open-loop vision result: " .. json.encode(vision_result))`);
    }
  }
  hasDefined() {
    return true;
  }
  getTitle() {
    const language = (0, scope_setting_1.getCurrentLanguage)();
    return translation_util_1.default.toAimLanguage(language, 'Track Motion', translation_util_1.TranslationNamespace.AGV);
  }
  getIcon(hasDefined) {
    return hasDefined ? `icon${agv_constant_1.PluginsProgramNodeId.AUBO_OPENLOOP}Complete` : `icon${agv_constant_1.PluginsProgramNodeId.AUBO_OPENLOOP}`;
  }
}
exports.OpenLoopNode = OpenLoopNode;
//# sourceMappingURL=openloop-node.js.map