import {TypedAnimNode} from "./_Base";
import {TimelineBuilder as TimelineBuilder2} from "../../../core/animation/TimelineBuilder";
import {CoreType} from "../../../core/Type";
import {TypeAssert} from "../../poly/Assert";
import {Quaternion as Quaternion2} from "three/src/math/Quaternion";
var PropertyValueMode;
(function(PropertyValueMode2) {
  PropertyValueMode2["CUSTOM"] = "custom";
  PropertyValueMode2["FROM_SCENE_GRAPH"] = "from scene graph";
  PropertyValueMode2["FROM_NODE"] = "from node";
})(PropertyValueMode || (PropertyValueMode = {}));
const PROPERTY_VALUE_MODES = [
  PropertyValueMode.CUSTOM,
  PropertyValueMode.FROM_SCENE_GRAPH,
  PropertyValueMode.FROM_NODE
];
const PROPERTY_VALUE_MODE_CUSTOM = PROPERTY_VALUE_MODES.indexOf(PropertyValueMode.CUSTOM);
const PROPERTY_VALUE_MODE_FROM_SCENE_GRAPH = PROPERTY_VALUE_MODES.indexOf(PropertyValueMode.FROM_SCENE_GRAPH);
const PROPERTY_VALUE_MODE_FROM_NODE = PROPERTY_VALUE_MODES.indexOf(PropertyValueMode.FROM_NODE);
import {NodeParamsConfig, ParamConfig} from "../utils/params/ParamsConfig";
class PropertyValueAnimParamsConfig extends NodeParamsConfig {
  constructor() {
    super(...arguments);
    this.mode = ParamConfig.INTEGER(PROPERTY_VALUE_MODE_CUSTOM, {
      menu: {
        entries: PROPERTY_VALUE_MODES.map((name, value) => {
          return {name, value};
        })
      }
    });
    this.nodePath = ParamConfig.NODE_PATH("/geo1", {
      visibleIf: {mode: PROPERTY_VALUE_MODE_FROM_NODE}
    });
    this.objectMask = ParamConfig.STRING("/geo1", {
      visibleIf: {mode: PROPERTY_VALUE_MODE_FROM_SCENE_GRAPH}
    });
    this.overridePropertyName = ParamConfig.BOOLEAN(0, {
      visibleIf: [{mode: PROPERTY_VALUE_MODE_FROM_SCENE_GRAPH}, {mode: PROPERTY_VALUE_MODE_FROM_NODE}]
    });
    this.propertyName = ParamConfig.STRING("", {
      visibleIf: [
        {overridePropertyName: true, mode: PROPERTY_VALUE_MODE_FROM_SCENE_GRAPH},
        {overridePropertyName: true, mode: PROPERTY_VALUE_MODE_FROM_NODE}
      ]
    });
    this.size = ParamConfig.INTEGER(3, {
      range: [1, 4],
      rangeLocked: [true, true],
      visibleIf: {mode: PROPERTY_VALUE_MODE_CUSTOM}
    });
    this.value1 = ParamConfig.FLOAT(0, {
      visibleIf: {mode: PROPERTY_VALUE_MODE_CUSTOM, size: 1}
    });
    this.value2 = ParamConfig.VECTOR2([0, 0], {
      visibleIf: {mode: PROPERTY_VALUE_MODE_CUSTOM, size: 2}
    });
    this.value3 = ParamConfig.VECTOR3([0, 0, 0], {
      visibleIf: {mode: PROPERTY_VALUE_MODE_CUSTOM, size: 3}
    });
    this.value4 = ParamConfig.VECTOR4([0, 0, 0, 0], {
      visibleIf: {mode: PROPERTY_VALUE_MODE_CUSTOM, size: 4}
    });
  }
}
const ParamsConfig2 = new PropertyValueAnimParamsConfig();
export class PropertyValueAnimNode extends TypedAnimNode {
  constructor() {
    super(...arguments);
    this.params_config = ParamsConfig2;
  }
  static type() {
    return "propertyValue";
  }
  initializeNode() {
    this.io.inputs.setCount(0, 1);
  }
  async cook(input_contents) {
    const timeline_builder = input_contents[0] || new TimelineBuilder2();
    await this._prepare_timeline_builder(timeline_builder);
    this.set_timeline_builder(timeline_builder);
  }
  async _prepare_timeline_builder(timeline_builder) {
    const mode = PROPERTY_VALUE_MODES[this.pv.mode];
    switch (mode) {
      case PropertyValueMode.CUSTOM: {
        return this._prepare_timebuilder_custom(timeline_builder);
      }
      case PropertyValueMode.FROM_SCENE_GRAPH: {
        return this._prepare_timebuilder_from_scene_graph(timeline_builder);
      }
      case PropertyValueMode.FROM_NODE: {
        return await this._prepare_timebuilder_from_node(timeline_builder);
      }
    }
    TypeAssert.unreachable(mode);
  }
  _prepare_timebuilder_custom(timeline_builder) {
    const target_value = [this.pv.value1, this.pv.value2.clone(), this.pv.value3.clone(), this.pv.value4.clone()][this.pv.size - 1];
    timeline_builder.setPropertyValue(target_value);
  }
  _prepare_timebuilder_from_scene_graph(timeline_builder) {
    const property_name = this.pv.overridePropertyName ? this.pv.propertyName : timeline_builder.propertyName();
    if (!property_name) {
      return;
    }
    const found_object = this.scene().findObjectByMask(this.pv.objectMask);
    if (found_object) {
      const value = found_object[property_name];
      if (value) {
        if (CoreType.isNumber(value) || CoreType.isVector(value) || value instanceof Quaternion2) {
          timeline_builder.setPropertyValue(value);
        }
      }
    }
  }
  async _prepare_timebuilder_from_node(timeline_builder) {
    const property_name = this.pv.overridePropertyName ? this.pv.propertyName : timeline_builder.propertyName();
    if (!property_name) {
      return;
    }
    const node = this.pv.nodePath.node();
    if (!node) {
      return;
    }
    const param = node.params.get(property_name);
    if (!param) {
      return;
    }
    if (param.isDirty()) {
      await param.compute();
    }
    const value = param.value;
    if (value) {
      if (CoreType.isNumber(value) || CoreType.isVector(value)) {
        timeline_builder.setPropertyValue(value);
      }
    }
  }
}
