import {WebGLRenderer as WebGLRenderer2} from "three/src/renderers/WebGLRenderer";
import {Vector2 as Vector22} from "three/src/math/Vector2";
import {NodeContext as NodeContext2} from "../../../../poly/NodeContext";
import {SceneObjNode} from "../../Scene";
import {Poly as Poly2} from "../../../../Poly";
import {
  WebGlRendererRopNode,
  DEFAULT_SHADOW_MAP_TYPE,
  DEFAULT_OUTPUT_ENCODING,
  DEFAULT_TONE_MAPPING
} from "../../../rop/WebGlRenderer";
import {RopType} from "../../../../poly/registers/nodes/Rop";
import {ParamConfig} from "../../../utils/params/ParamsConfig";
export function CameraRenderParamConfig(Base) {
  return class Mixin extends Base {
    constructor() {
      super(...arguments);
      this.render = ParamConfig.FOLDER();
      this.setScene = ParamConfig.BOOLEAN(0);
      this.scene = ParamConfig.OPERATOR_PATH("/scene1", {
        visibleIf: {setScene: 1},
        nodeSelection: {
          context: NodeContext2.OBJ,
          types: [SceneObjNode.type()]
        }
      });
      this.setRenderer = ParamConfig.BOOLEAN(0);
      this.renderer = ParamConfig.OPERATOR_PATH("./renderers1/webGlRenderer1", {
        visibleIf: {setRenderer: 1},
        nodeSelection: {
          context: NodeContext2.ROP,
          types: [WebGlRendererRopNode.type()]
        }
      });
      this.setCssRenderer = ParamConfig.BOOLEAN(0);
      this.cssRenderer = ParamConfig.OPERATOR_PATH("./renderers1/css2DRenderer1", {
        visibleIf: {setCssRenderer: 1},
        nodeSelection: {
          context: NodeContext2.ROP,
          types: [RopType.CSS2D, RopType.CSS3D]
        }
      });
    }
  };
}
export class RenderController {
  constructor(node) {
    this.node = node;
    this._renderers_by_canvas_id = {};
    this._resolution_by_canvas_id = {};
    this._super_sampling_size = new Vector22();
  }
  render(canvas, size, aspect) {
    if (this.node.pv.doPostProcess) {
      this.node.post_process_controller.render(canvas, size);
    } else {
      this.render_with_renderer(canvas);
    }
    if (this._resolved_cssRenderer_rop && this._resolved_scene && this.node.pv.setCssRenderer) {
      const cssRenderer = this.cssRenderer(canvas);
      if (cssRenderer) {
        cssRenderer.render(this._resolved_scene, this.node.object);
      }
    }
  }
  render_with_renderer(canvas) {
    const renderer = this.renderer(canvas);
    if (renderer) {
      if (this._resolved_scene) {
        renderer.render(this._resolved_scene, this.node.object);
      }
    }
  }
  async update() {
    this.update_scene();
    this.update_renderer();
    this.update_cssRenderer();
  }
  get resolved_scene() {
    return this._resolved_scene;
  }
  update_scene() {
    if (this.node.pv.setScene) {
      const param = this.node.p.scene;
      if (param.isDirty()) {
        param.find_target();
      }
      const node = param.found_node_with_context_and_type(NodeContext2.OBJ, SceneObjNode.type());
      if (node) {
        if (node.isDirty()) {
          node.cookController.cook_main_without_inputs();
        }
        this._resolved_scene = node.object;
      }
    } else {
      this._resolved_scene = this.node.scene().threejsScene();
    }
  }
  update_renderer() {
    if (this.node.pv.setRenderer) {
      const param = this.node.p.renderer;
      if (param.isDirty()) {
        param.find_target();
      }
      this._resolved_renderer_rop = param.found_node_with_context_and_type(NodeContext2.ROP, RopType.WEBGL);
    } else {
      this._resolved_renderer_rop = void 0;
    }
  }
  update_cssRenderer() {
    if (this.node.pv.setCssRenderer) {
      const param = this.node.p.cssRenderer;
      if (param.isDirty()) {
        param.find_target();
      }
      this._resolved_cssRenderer_rop = param.found_node_with_context_and_type(NodeContext2.ROP, [
        RopType.CSS2D,
        RopType.CSS3D
      ]);
    } else {
      if (this._resolved_cssRenderer_rop) {
      }
      this._resolved_cssRenderer_rop = void 0;
    }
  }
  renderer(canvas) {
    return this._renderers_by_canvas_id[canvas.id];
  }
  cssRenderer(canvas) {
    if (this._resolved_cssRenderer_rop && this.node.pv.setCssRenderer) {
      return this._resolved_cssRenderer_rop.renderer(canvas);
    }
  }
  createRenderer(canvas, size) {
    const gl = Poly2.renderersController.renderingContext(canvas);
    if (!gl) {
      console.error("failed to create webgl context");
      return;
    }
    let renderer;
    if (this.node.pv.setRenderer) {
      this.update_renderer();
      if (this._resolved_renderer_rop) {
        renderer = this._resolved_renderer_rop.create_renderer(canvas, gl);
      }
    }
    if (!renderer) {
      renderer = RenderController._create_default_renderer(canvas, gl);
    }
    Poly2.renderersController.registerRenderer(renderer);
    this._renderers_by_canvas_id[canvas.id] = renderer;
    this._super_sampling_size.copy(size);
    if (renderer.sampling) {
      this._super_sampling_size.multiplyScalar(renderer.sampling);
    }
    this.set_renderer_size(canvas, this._super_sampling_size);
    return renderer;
  }
  static _create_default_renderer(canvas, gl) {
    const renderer = new WebGLRenderer2({
      canvas,
      antialias: true,
      alpha: true,
      context: gl
    });
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = DEFAULT_SHADOW_MAP_TYPE;
    renderer.physicallyCorrectLights = true;
    renderer.toneMapping = DEFAULT_TONE_MAPPING;
    renderer.toneMappingExposure = 1;
    renderer.outputEncoding = DEFAULT_OUTPUT_ENCODING;
    return renderer;
  }
  delete_renderer(canvas) {
    const renderer = this.renderer(canvas);
    if (renderer) {
      Poly2.renderersController.deregisterRenderer(renderer);
    }
  }
  canvas_resolution(canvas) {
    return this._resolution_by_canvas_id[canvas.id];
  }
  set_renderer_size(canvas, size) {
    this._resolution_by_canvas_id[canvas.id] = this._resolution_by_canvas_id[canvas.id] || new Vector22();
    this._resolution_by_canvas_id[canvas.id].copy(size);
    const renderer = this.renderer(canvas);
    if (renderer) {
      const update_style = false;
      renderer.setSize(size.x, size.y, update_style);
    }
    if (this._resolved_cssRenderer_rop) {
      const cssRenderer = this.cssRenderer(canvas);
      if (cssRenderer) {
        cssRenderer.setSize(size.x, size.y);
      }
    }
  }
}
