import {BaseNodeGlMathFunctionArg2GlNode} from "./_BaseMathFunction";
import {GlConnectionPointType} from "../utils/io/connections/Gl";
import {ThreeToGl as ThreeToGl2} from "../../../core/ThreeToGl";
function MathFunctionArg2OperationFactory(type, options) {
  const in_prefix = options.in_prefix || type;
  const output_name = options.out || "val";
  const operation = options.operation;
  const allowed_in_types = options.allowed_in_types;
  return class Node extends BaseNodeGlMathFunctionArg2GlNode {
    static type() {
      return type;
    }
    initializeNode() {
      super.initializeNode();
      this.io.connection_points.set_input_name_function(this._gl_input_name.bind(this));
      this.io.connection_points.set_output_name_function(this._gl_output_name.bind(this));
      this.io.connection_points.set_expected_input_types_function(this._expected_input_types.bind(this));
      this.io.connection_points.set_expected_output_types_function(this._expected_output_types.bind(this));
    }
    set_lines(shaders_collection_controller) {
      const var_type = this.io.outputs.named_output_connection_points[0].type();
      const args = this.io.inputs.named_input_connection_points.map((connection, i) => {
        const name = connection.name();
        const variable = this.variable_for_input(name);
        if (variable) {
          return ThreeToGl2.any(variable);
        }
      });
      const joined_args = args.join(` ${this.gl_operation()} `);
      const sum = this.gl_var_name(this.io.connection_points.output_name(0));
      const body_line = `${var_type} ${sum} = ${this.gl_method_name()}(${joined_args})`;
      shaders_collection_controller.add_body_lines(this, [body_line]);
    }
    _gl_input_name(index) {
      return `${in_prefix}${index}`;
    }
    _gl_output_name(index) {
      return output_name;
    }
    gl_operation() {
      return operation;
    }
    _expected_input_types() {
      let first_input_type = this.io.connection_points.first_input_connection_type();
      if (first_input_type && allowed_in_types) {
        if (!allowed_in_types.includes(first_input_type)) {
          const first_connection = this.io.inputs.named_input_connection_points[0];
          if (first_connection) {
            first_input_type = first_connection.type();
          }
        }
      }
      const type2 = first_input_type || GlConnectionPointType.FLOAT;
      const current_connections = this.io.connections.input_connections();
      const expected_count = current_connections ? Math.max(current_connections.length + 1, 2) : 2;
      const expected_input_types = [];
      for (let i = 0; i < expected_count; i++) {
        expected_input_types.push(type2);
      }
      return expected_input_types;
    }
    _expected_output_types() {
      const input_types = this._expected_input_types();
      const type2 = input_types[1] || input_types[0] || GlConnectionPointType.FLOAT;
      return [type2];
    }
  };
}
export class AddGlNode extends MathFunctionArg2OperationFactory("add", {
  in_prefix: "add",
  out: "sum",
  operation: "+"
}) {
}
export class DivideGlNode extends MathFunctionArg2OperationFactory("divide", {
  in_prefix: "div",
  out: "divide",
  operation: "/"
}) {
  param_default_value(name) {
    return 1;
  }
}
export class SubstractGlNode extends MathFunctionArg2OperationFactory("substract", {
  in_prefix: "sub",
  out: "substract",
  operation: "-"
}) {
}
export class MultGlNode extends MathFunctionArg2OperationFactory("mult", {
  in_prefix: "mult",
  out: "product",
  operation: "*"
}) {
  static type() {
    return "mult";
  }
  param_default_value(name) {
    return 1;
  }
  initializeNode() {
    super.initializeNode();
    this.io.connection_points.set_expected_input_types_function(this._expected_input_types.bind(this));
    this.io.connection_points.set_expected_output_types_function(this._expected_output_types.bind(this));
  }
  _expected_output_type() {
    const input_types = this._expected_input_types();
    const type = input_types[input_types.length - 1];
    return [type];
  }
  _expected_input_types() {
    const input_connections = this.io.connections.input_connections();
    if (input_connections) {
      const first_connection = input_connections[0];
      if (first_connection) {
        const connection_point_for_first_connection = first_connection.node_src.io.outputs.named_output_connection_points[first_connection.output_index];
        const type = connection_point_for_first_connection.type();
        const expected_count = Math.max(input_connections.length + 1, 2);
        const empty_array = new Array(expected_count);
        if (type == GlConnectionPointType.FLOAT) {
          const second_connection = input_connections[1];
          if (second_connection) {
            const connection_point_for_second_connection = second_connection.node_src.io.outputs.named_output_connection_points[second_connection.output_index];
            const second_type = connection_point_for_second_connection.type();
            if (second_type == GlConnectionPointType.FLOAT) {
              return empty_array.fill(type);
            } else {
              return [type, second_type];
            }
          } else {
            return [type, type];
          }
        } else {
          return empty_array.fill(type);
        }
      } else {
      }
    }
    return [GlConnectionPointType.FLOAT, GlConnectionPointType.FLOAT];
  }
}
