import {ACCEPTED_SCENE_EVENT_TYPES} from "../../scene/utils/events/SceneEventsController";
import {EventConnectionPoint, EventConnectionPointType} from "../utils/io/connections/Event";
import {TypedInputEventNode, EVENT_PARAM_OPTIONS} from "./_BaseInput";
var SceneNodeInput;
(function(SceneNodeInput2) {
  SceneNodeInput2["SET_FRAME"] = "setFrame";
})(SceneNodeInput || (SceneNodeInput = {}));
var SceneNodeOutput;
(function(SceneNodeOutput2) {
  SceneNodeOutput2["TIME_REACHED"] = "timeReached";
})(SceneNodeOutput || (SceneNodeOutput = {}));
import {NodeParamsConfig, ParamConfig} from "../utils/params/ParamsConfig";
import {CoreGraphNode as CoreGraphNode2} from "../../../core/graph/CoreGraphNode";
class SceneEventParamsConfig extends NodeParamsConfig {
  constructor() {
    super(...arguments);
    this.active = ParamConfig.BOOLEAN(true, {
      callback: (node, param) => {
        SceneEventNode.PARAM_CALLBACK_update_register(node);
      }
    });
    this.sep = ParamConfig.SEPARATOR(null, {visibleIf: {active: true}});
    this.sceneLoaded = ParamConfig.BOOLEAN(1, EVENT_PARAM_OPTIONS);
    this.play = ParamConfig.BOOLEAN(1, EVENT_PARAM_OPTIONS);
    this.pause = ParamConfig.BOOLEAN(1, EVENT_PARAM_OPTIONS);
    this.tick = ParamConfig.BOOLEAN(1, EVENT_PARAM_OPTIONS);
    this.sep0 = ParamConfig.SEPARATOR();
    this.treachedTime = ParamConfig.BOOLEAN(0, {
      callback: (node) => {
        SceneEventNode.PARAM_CALLBACK_update_time_dependency(node);
      }
    });
    this.reachedTime = ParamConfig.INTEGER(10, {
      visibleIf: {treachedTime: 1},
      range: [0, 100]
    });
    this.sep1 = ParamConfig.SEPARATOR();
    this.setFrameValue = ParamConfig.INTEGER(1, {
      range: [0, 100]
    });
    this.setFrame = ParamConfig.BUTTON(null, {
      callback: (node) => {
        SceneEventNode.PARAM_CALLBACK_setFrame(node);
      }
    });
  }
}
const ParamsConfig2 = new SceneEventParamsConfig();
export class SceneEventNode extends TypedInputEventNode {
  constructor() {
    super(...arguments);
    this.params_config = ParamsConfig2;
  }
  static type() {
    return "scene";
  }
  accepted_event_types() {
    return ACCEPTED_SCENE_EVENT_TYPES.map((n) => `${n}`);
  }
  dispose() {
    this.graph_node?.dispose();
    super.dispose();
  }
  initializeNode() {
    this.io.inputs.setNamedInputConnectionPoints([
      new EventConnectionPoint(SceneNodeInput.SET_FRAME, EventConnectionPointType.BASE, this.onSetFrame.bind(this))
    ]);
    const out_connection_points = ACCEPTED_SCENE_EVENT_TYPES.map((event_type) => {
      return new EventConnectionPoint(event_type, EventConnectionPointType.BASE);
    });
    out_connection_points.push(new EventConnectionPoint(SceneNodeOutput.TIME_REACHED, EventConnectionPointType.BASE));
    this.io.outputs.setNamedOutputConnectionPoints(out_connection_points);
    this.params.onParamsCreated("update_time_dependency", () => {
      this.update_time_dependency();
    });
  }
  onSetFrame(event_context) {
    this.scene().setFrame(this.pv.setFrameValue);
  }
  on_frame_update() {
    if (this.scene().time() >= this.pv.reachedTime) {
      this.dispatch_event_to_output(SceneNodeOutput.TIME_REACHED, {});
    }
  }
  update_time_dependency() {
    if (this.pv.treachedTime) {
      this.graph_node = this.graph_node || new CoreGraphNode2(this.scene(), "scene_node_time_graph_node");
      this.graph_node.addGraphInput(this.scene().timeController.graph_node);
      this.graph_node.addPostDirtyHook("time_update", this.on_frame_update.bind(this));
    } else {
      if (this.graph_node) {
        this.graph_node.graphDisconnectPredecessors();
      }
    }
  }
  static PARAM_CALLBACK_setFrame(node) {
    node.onSetFrame({});
  }
  static PARAM_CALLBACK_update_time_dependency(node) {
    node.update_time_dependency();
  }
}
