import { Raycaster, Scene, Vector3, WebGLRenderer, type WebGLRendererParameters, Object3D, Mesh, Line, Points, Material, Texture } from "three";
import { cZeroVec, GetBox, GetBoxArr } from "./GeUtils";
import { PlaneExt } from "./PlaneExt";
import { CameraType, CameraUpdate } from "webcad_ue4_api";
import { disposeNode } from "../helpers/helper.three";


export class Viewer {
    m_LookTarget: any;
    m_Camera: CameraUpdate = new CameraUpdate();
    protected NeedUpdate: boolean = true;
    Renderer!: WebGLRenderer; // 在 initRender 中初始化，使用 ! 断言
    m_DomEl: HTMLElement;

    _Height: number = 0;
    _Width: number = 0;

    _Scene: Scene = new Scene();

    private m_IsDisposed: boolean = false; // 添加一个标志来停止渲染循环和防止重复释放
    private m_AnimationFrameId: number | null = null; // 用于取消动画帧

    get Scene() {
        return this._Scene;
    }

    get Fov() {
        return this.m_Camera.Fov;
    }

    set Fov(val: number) {
        this.m_Camera.Fov = val;
        this.NeedUpdate = true;
    }

    UpdateRender() {
        this.NeedUpdate = true;
    }

    constructor(canvasContainer: HTMLElement) {
        this.m_DomEl = canvasContainer;
        this.initRender(canvasContainer);
        this.SetSize(); // 初始尺寸设置
        this.StartRender(); // 开始渲染循环

        // 注意: OnSize 是一个箭头函数属性，它的 this 上下文是固定的
        // 因此可以直接用于添加和移除事件监听器
        window.addEventListener("resize", this.OnResize);
        this.InitCamera();
    }

    initRender(canvasContainer: HTMLElement) {
        let params: WebGLRendererParameters = {
            antialias: true,
            precision: "highp",
            alpha: true
        };
        this.Renderer = new WebGLRenderer(params);
        canvasContainer.appendChild(this.Renderer.domElement);
        this.Renderer.autoClear = true;
        this.Renderer.setPixelRatio(window.devicePixelRatio);
        this.Renderer.physicallyCorrectLights = true; //  r150 后默认 false, 根据需要设置
        this.Renderer.setClearColor(0xffffff, 1);
        // this.OnSize(); // 在构造函数中调用，这里可以不用重复
    }

    InitCamera() {
        this.m_Camera.CameraType = CameraType.PerspectiveCamera;
        this.m_Camera.Near = 0.001;
        if (this.m_Camera.Camera) { // 确保 CameraUpdate 内部的 Camera 已初始化
            this.m_Camera.Camera.far = 1000000000;
        }
    }

    OnResize = (evt: UIEvent) => this.SetSize();

    SetSize = (width?: number, height?: number) => {
        if (this.m_IsDisposed || !this.m_DomEl) return; // 如果已销毁或容器不存在，则不执行

        this._Width = width ? width : this.m_DomEl.clientWidth;
        this._Height = height ? height : this.m_DomEl.clientHeight;

        if (this._Width % 2 === 1) this._Width -= 1;
        if (this._Height % 2 === 1) this._Height -= 1;

        if (this.Renderer) {
            this.Renderer.setSize(this._Width, this._Height);
        }
        if (this.m_Camera) {
            this.m_Camera.SetSize(this._Width, this._Height);
        }
        this.NeedUpdate = true; // 尺寸变化后需要重新渲染
    };

    StartRender = () => {
        if (this.m_IsDisposed) {
            if (this.m_AnimationFrameId !== null) {
                cancelAnimationFrame(this.m_AnimationFrameId);
                this.m_AnimationFrameId = null;
            }
            return;
        }
        this.m_AnimationFrameId = requestAnimationFrame(this.StartRender);

        if (this._Scene && this.NeedUpdate) { // 确保 _Scene 存在
            this.Render();
            if (this.m_Camera) { // 确保 m_Camera 存在
                this.m_Camera.Update();
            }
            this.NeedUpdate = false;
        }
    };

    Render() {
        if (this.m_IsDisposed || !this.Renderer || !this._Scene || !this.m_Camera || !this.m_Camera.Camera) {
            return;
        }
        this.Renderer.render(this._Scene, this.m_Camera.Camera);
    }

    // ScreenToWorld, WorldToScreen, UpdateLockTarget, Rotate, Pan, Zoom, etc. methods remain the same...
    // ... (省略了您提供的其他方法，它们与 dispose 无直接关系，保持不变) ...
    ScreenToWorld(pt: Vector3, planVec?: Vector3) {
        if (this.m_IsDisposed || !this._Scene || !this.m_Camera || !this.m_Camera.Camera) return;
        //变换和求交点
        let plan = new PlaneExt(planVec || new Vector3(0, 0, 1));
        let raycaster = new Raycaster();
        // 射线从相机射线向屏幕点位置
        raycaster.setFromCamera(
            {
                x: (pt.x / this._Width) * 2 - 1,
                y: - (pt.y / this._Height) * 2 + 1
            }
            , this.m_Camera.Camera
        );
        plan.intersectRay(raycaster.ray, pt, true); // 假设 intersectRay 修改 pt
    }
    WorldToScreen(pt: Vector3) {
        if (this.m_IsDisposed || !this.m_Camera || !this.m_Camera.Camera) return;
        let widthHalf = this._Width * 0.5;
        let heightHalf = this._Height * 0.5;

        pt.project(this.m_Camera.Camera);

        pt.x = (pt.x * widthHalf) + widthHalf;
        pt.y = - (pt.y * heightHalf) + heightHalf;
    }

    UpdateLockTarget() {
        if (this.m_IsDisposed || !this.Renderer || !this._Scene || !this.m_Camera || !this.m_Camera.Camera) return;
        // @ts-ignore access to private renderLists
        const renderList = this.Renderer.renderLists.get(this._Scene, this.m_Camera.Camera);
        // @ts-ignore
        const box = GetBoxArr(renderList.opaque.map(o => o.object)); // 确保 GetBoxArr 定义正确
        if (box)
            // @ts-ignore
            this.m_LookTarget = box.getCenter(new Vector3());
        else
            // @ts-ignore
            this.m_LookTarget = cZeroVec; // 确保 cZeroVec 定义正确
    }
    Rotate(mouseMove: Vector3) {
        if (this.m_IsDisposed || !this.m_Camera) return;
        this.m_Camera.Rotate(mouseMove, this.m_LookTarget);
        this.NeedUpdate = true;
    }
    RotateAround(movement: Vector3, center: Vector3) {
        if (this.m_IsDisposed || !this.m_Camera) return;
        this.m_Camera.Rotate(movement, center);
        this.NeedUpdate = true;
    }
    Pan(mouseMove: Vector3) {
        if (this.m_IsDisposed || !this.m_Camera) return;
        this.m_Camera.Pan(mouseMove);
        this.NeedUpdate = true;
    }
    Zoom(scale: number, center?: Vector3) {
        if (this.m_IsDisposed || !this.m_Camera) return;
        this.m_Camera.Zoom(scale, center);
        this.NeedUpdate = true;
    }
    ZoomAll() {
        if (this.m_IsDisposed || !this.m_Camera || !this._Scene) return;
        // @ts-ignore
        this.m_Camera.ZoomExtentsBox3(GetBox(this._Scene, true)); // 确保 GetBox 定义正确
        this.NeedUpdate = true;
    }

    ViewToTop() {
        if (this.m_IsDisposed || !this.m_Camera) return;
        this.m_Camera.LookAt(new Vector3(0, 0, -1));
        this.NeedUpdate = true;
    }
    ViewToFront() {
        if (this.m_IsDisposed || !this.m_Camera) return;
        this.m_Camera.LookAt(new Vector3(0, 1, 0));
        this.NeedUpdate = true;
    }
    ViewToSwiso() {
        if (this.m_IsDisposed || !this.m_Camera) return;
        this.m_Camera.LookAt(new Vector3(1, 1, -1));
        this.NeedUpdate = true;
    }


    /**
     * 销毁 Viewer 实例并释放所有相关资源。
     */
    public Dispose(): void {
        if (this.m_IsDisposed) {
            return; // 防止重复释放
        }

        console.log("Disposing Viewer...");

        // 1. 停止渲染循环
        this.m_IsDisposed = true; // 设置标志，渲染循环将在下一帧停止
        if (this.m_AnimationFrameId !== null) {
            cancelAnimationFrame(this.m_AnimationFrameId);
            this.m_AnimationFrameId = null;
        }


        // 2. 移除事件监听器
        window.removeEventListener("resize", this.OnResize);
        // 如果 m_DomEl 上有其他直接添加的事件监听器，也应在此移除

        // 3. 销毁场景内容 (几何体、材质、纹理)
        if (this._Scene) {
            // 遍历场景中的所有对象并释放它们的资源
            this._Scene.traverse((object) => {
                disposeNode(object);
            });

            // 从场景中移除所有子对象
            // scene.clear() 也可以，但在此之前我们已经遍历并释放了资源
            while (this._Scene.children.length > 0) {
                const child = this._Scene.children[0];
                // 确保子对象的资源已通过上面的 traverse 处理
                this._Scene.remove(child);
            }
            // console.log("Scene cleared and resources disposed.");
        }


        // 4. 销毁渲染器
        if (this.Renderer) {
            // @ts-ignore access to private renderLists
            if (this.Renderer.renderLists) { // 检查 renderLists 是否存在
                // @ts-ignore
                this.Renderer.renderLists.dispose();
                // console.log("Renderer renderLists disposed.");
            }
            this.Renderer.dispose();
            // console.log("Renderer disposed.");

            // 从 DOM 中移除渲染器的 canvas 元素
            if (this.Renderer.domElement && this.Renderer.domElement.parentElement) {
                this.Renderer.domElement.parentElement.removeChild(this.Renderer.domElement);
                // console.log("Renderer DOM element removed.");
            }
        }

        // 5. 清除引用 (帮助垃圾回收)
        // @ts-ignore
        this._Scene = null;
        // @ts-ignore
        this.Renderer = null;
        // @ts-ignore
        this.m_DomEl = null;
        // @ts-ignore
        this.m_Camera = null;
        // @ts-ignore
        this.m_LookTarget = null;

        console.log("Viewer disposed successfully.");
    }
}