import * as THREE from "three";
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { TTFLoader } from "three/examples/jsm/loaders/TTFLoader.js";
import { SSAARenderPass } from "three/examples/jsm/postprocessing/SSAARenderPass.js";
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass.js";
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
import { OutputPass } from 'three/examples/jsm/postprocessing/OutputPass.js';
import {
    addTriangleFacingCamera,
    getBSplinePolyline, getBulgeCurvePoints,
    mtextContentAndFormattingToTextAndStyle
} from "./drawUtils";
// @ts-ignore
import { parseDxfMTextContent } from "@dxfom/mtext";
import { Font } from "three/examples/jsm/loaders/FontLoader.js";
import { PickHelper } from "./pickHelper";
import { DrawRect } from "./drawRect";

let signal, middleObject;
let scene, helpScene, camera, renderer, inputElement, font, data;

// 渲染辉光图层
let composer, finalComposer;
const BLOOM_SCENE = 10;
const bloomLayer = new THREE.Layers();
bloomLayer.set(BLOOM_SCENE);
const DarkMaterial = new THREE.MeshBasicMaterial({ color: 'black' });
const materials = {};

let modules: any = {};

// TODO 当前解析模式会存在 data.blocks 中还有实体但未匹配解析的情况；
// 记录已经解析的 data.blocks,data.entities遍历完成后处理
let parsedBlocks: string[] = [];
// 渲染配置项 && 对比度颜色实体集合
let options = {
    bgColor: 0x000000,
    contrastColor: 0xffffff
}, contrastEntity: any = [];

// canvas默认宽高
export const state = {
    width: 500,
    height: 500,
};

/**
 * 离屏canvas和普通canvas共用的绘制图纸方法
 * 优先级：offScreenCanvas > canvas
 */
export function main(d) {
    const { canvas, onComplete } = d;
    signal = d.signal;
    middleObject = d.middleObject;
    state.width = canvas.width;
    state.height = canvas.height;
    inputElement = d.inputElement;
    data = d.data;
    // cad配置项
    options = Object.assign(options, d.options);
    options.bgColor = Number(options.bgColor);
    options.contrastColor = options.bgColor === 0x000000 ? 0xffffff : 0x000000;

    createLineTypeShaders();

    renderer = new THREE.WebGLRenderer({
        canvas,
        powerPreference: "high-performance",
        depth: false,
        antialias: true,
    });
    // 第三个参数false代表不更新canvas dom style
    renderer.setSize(canvas.width, canvas.height, false);
    renderer.setClearColor(options.bgColor, 1);
    renderer.toneMapping = THREE.ReinhardToneMapping;
    // renderer.autoClear = false;

    const loader = new TTFLoader();
    loader.loadAsync("/upyun/assets/font/Alimama_DongFangDaKai_Regular.ttf").then(function (response) {
        font = new Font(response);

        init();

        // OrbitControls mousemove事件中未调用chang事件，所以需要一直渲染
        renderLoop();

        // 添加灯光
        scene.add(new THREE.AmbientLight(0xffffff, 1));

        // 后期通道
        initComposer();

        const controls = new OrbitControls(camera, inputElement);
        controls.target.x = camera.position.x;
        controls.target.y = camera.position.y;
        controls.target.z = 0;
        controls.mouseButtons = { LEFT: THREE.MOUSE.PAN, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.ROTATE };
        controls.enableRotate = false;
        controls.update();

        modules.drawRect.setControls(controls);

        const pickPosition = new THREE.Vector2(0, 0);
        modules.pickHelper = new PickHelper(scene, camera, BLOOM_SCENE);
        clearPickPosition();

        function getCanvasRelativePosition(event) {
            const rect = inputElement.getBoundingClientRect();
            return {
                x: event.clientX - rect.left,
                y: event.clientY - rect.top,
            };
        }

        function setPickPosition(event) {
            const pos = getCanvasRelativePosition(event);
            pickPosition.x = (pos.x / state.width) * 2 - 1;
            pickPosition.y = (pos.y / state.height) * - 2 + 1;

            modules.pickHelper.pick(pickPosition);
        }

        function clearPickPosition() {
            //不像鼠标总是有一个位置，如果用户停止触摸屏幕，我们想要停止。现在我们只取一个不太可能取到的值
            pickPosition.x = - 100000;
            pickPosition.y = - 100000;
        }

        inputElement.addEventListener('mousemove', setPickPosition);
        inputElement.addEventListener('mouseout', clearPickPosition);
        inputElement.addEventListener('mouseleave', clearPickPosition);

        inputElement.addEventListener('touchstart', (event) => {
            // 防止窗口滚动
            event.preventDefault();
            setPickPosition(event.touches[0]);
        }, { passive: false });
        inputElement.addEventListener('touchmove', (event) => {
            setPickPosition(event.touches[0]);
        });
        inputElement.addEventListener('touchend', clearPickPosition);

        // 加载完毕
        onComplete && onComplete();

        font = undefined;
        data = undefined;

        resize({ width: inputElement.width, height: inputElement.height });
    });
}

function createLineTypeShaders() {
    let ltype, type;
    if (!data.tables || !data.tables.lineType) return;
    const ltypes = data.tables.lineType.lineTypes;

    for (type in ltypes) {
        ltype = ltypes[type];
        if (!ltype.pattern) continue;
        ltype.material = createDashedLineShader(ltype.pattern);
    }
}

function createDashedLineShader(pattern) {
    let dashedLineShader: any = {},
        totalLength = 0.0;

    for (let i = 0; i < pattern.length; i++) {
        totalLength += Math.abs(pattern[i]);
    }

    dashedLineShader.uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib['common'],
        THREE.UniformsLib['fog'],

        {
            // @ts-ignore
            'pattern': { type: 'fv1', value: pattern },
            // @ts-ignore
            'patternLength': { type: 'f', value: totalLength }
        }
    ]);

    dashedLineShader.vertexShader = [
        'attribute float lineDistance;',

        'varying float vLineDistance;',

        THREE.ShaderChunk['color_pars_vertex'],

        'void main() {',

        THREE.ShaderChunk['color_vertex'],

        'vLineDistance = lineDistance;',

        'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',

        '}'
    ].join('\n');

    dashedLineShader.fragmentShader = [
        'uniform vec3 diffuse;',
        'uniform float opacity;',

        'uniform float pattern[' + pattern.length + '];',
        'uniform float patternLength;',

        'varying float vLineDistance;',

        THREE.ShaderChunk['color_pars_fragment'],
        THREE.ShaderChunk['fog_pars_fragment'],

        'void main() {',

        'float pos = mod(vLineDistance, patternLength);',

        'for ( int i = 0; i < ' + pattern.length + '; i++ ) {',
        'pos = pos - abs(pattern[i]);',
        'if( pos < 0.0 ) {',
        'if( pattern[i] > 0.0 ) {',
        'gl_FragColor = vec4(1.0, 0.0, 0.0, opacity );',
        'break;',
        '}',
        'discard;',
        '}',

        '}',

        THREE.ShaderChunk['color_fragment'],
        THREE.ShaderChunk['fog_fragment'],

        '}'
    ].join('\n');

    return dashedLineShader;
}

function init() {
    scene = new THREE.Scene();
    scene.background = new THREE.Color(options.bgColor);
    helpScene = new THREE.Scene();

    const layersGroupMap: Map<string, THREE.Group> = new Map();
    // 使用layers生成group
    for (let layerName in data.tables.layer.layers) {
        const layer = data.tables.layer.layers[layerName];
        const group = new THREE.Group();
        group.name = layerName;
        group.visible = layer.visible;

        layersGroupMap.set(layerName, group);
        scene.add(group);
    }

    // 通过dxf数据创建场景
    let entity, obj;
    // 生成所有实体
    for (let i = 0; i < data.entities.length; i++) {
        entity = data.entities[i];

        obj = drawEntity(entity);

        if (obj) {
            if (layersGroupMap.has(entity.layer)) {
                const parent = layersGroupMap.get(entity.layer) || scene;
                parent.add(obj);
                obj.name = `${entity.type}-${entity.handle || 'noHandle'}-${parent.children.length}`
            } else {
                scene.add(obj);
                obj.name = `${entity.type}-${entity.handle || 'noHandle'}-${scene.children.length}`
            }
        }
        obj = null;
    }

    // 2023-9-6:遍历所有剩下的未遍历的块，找出其中 INSERT/DIMENSION 类型的实体，进行解析.(非此类型就算解析位置也不正确)
    // TODO 待删除
    for (let blockName in data.blocks) {
        const block = data.blocks[blockName];

        if (parsedBlocks.includes(blockName) || !block.position || !block.entities) continue;

        for (let j = 0; j < block.entities.length; j++) {
            entity = block.entities[j];
            if (entity.type == "INSERT" || entity.type == "DIMENSION") {
                // TODO 容易栈溢出
                // obj = this.drawEntity(entity);
                //
                // if (obj) {
                //     const bbox = new THREE.Box3().setFromObject(obj);
                //     if (isFinite(bbox.min.x) && (dims.min.x > bbox.min.x)) dims.min.x = bbox.min.x;
                //     if (isFinite(bbox.min.y) && (dims.min.y > bbox.min.y)) dims.min.y = bbox.min.y;
                //     if (isFinite(bbox.min.z) && (dims.min.z > bbox.min.z)) dims.min.z = bbox.min.z;
                //     if (isFinite(bbox.max.x) && (dims.max.x < bbox.max.x)) dims.max.x = bbox.max.x;
                //     if (isFinite(bbox.max.y) && (dims.max.y < bbox.max.y)) dims.max.y = bbox.max.y;
                //     if (isFinite(bbox.max.z) && (dims.max.z < bbox.max.z)) dims.max.z = bbox.max.z;
                //     this.scene.add(obj);
                // }
                // obj = null;
            }
        }
    }

    const aspectRatio = state.width / state.height;
    const dims = new THREE.Box3().setFromObject(scene);
    const upperRightCorner = { x: dims.max.x, y: dims.max.y };
    const lowerLeftCorner = { x: dims.min.x, y: dims.min.y };
    //const lowerLeftCorner = data.header.$EXTMIN; // X、Y 和 Z 图形范围左下角（在 WCS 中）
    //const upperRightCorner = data.header.$EXTMAX; // X、Y 和 Z 图形范围右上角（在 WCS 中）

    // 找出当前的视口范围
    let vp_width = upperRightCorner.x - lowerLeftCorner.x;
    let vp_height = upperRightCorner.y - lowerLeftCorner.y;
    let center = {
        x: vp_width / 2 + lowerLeftCorner.x,
        y: vp_height / 2 + lowerLeftCorner.y
    };
    //let center = data.tables.viewPort.viewPorts[0].ucsOrigin;

    // 将所有对象放入当前的查看器中
    const extentsAspectRatio = Math.abs(vp_width / vp_height);
    if (aspectRatio > extentsAspectRatio) {
        vp_width = vp_height * aspectRatio;
    } else {
        vp_height = vp_width / aspectRatio;
    }

    const viewPort = {
        bottom: -vp_height / 2,
        left: -vp_width / 2,
        top: vp_height / 2,
        right: vp_width / 2,
        center: {
            x: center.x,
            y: center.y
        }
    };

    camera = new THREE.OrthographicCamera(viewPort.left, viewPort.right, viewPort.top, viewPort.bottom, 1, 19);
    camera.position.z = 1;
    camera.position.x = viewPort.center.x;
    camera.position.y = viewPort.center.y;
    camera.userData.viewPort = viewPort;

    // 注册模块
    modules.drawRect = new DrawRect(inputElement, helpScene, camera, signal, middleObject);

    // 销毁中间变量
    layersGroupMap.clear();
}

function initComposer() {
    const pixelRatio = renderer.getPixelRatio();

    composer = new EffectComposer(renderer);
    composer.renderToScreen = false;
    composer.setPixelRatio(pixelRatio)

    let ssaaRenderPass = new SSAARenderPass(scene, camera);
    ssaaRenderPass.unbiased = false;
    ssaaRenderPass.sampleLevel = 2;
    composer.addPass(ssaaRenderPass);

    const bloomPass = new UnrealBloomPass(
        //参数一：泛光覆盖场景大小，二维向量类型
        new THREE.Vector2(inputElement.width, inputElement.height),
        //参数二：bloomStrength 泛光强度，值越大明亮的区域越亮，较暗区域变亮的范围越广
        1.5,
        //参数三：bloomRadius 泛光散发半径
        0,
        //参数四：bloomThreshold 泛光的光照强度阈值，如果照在物体上的光照强度大于该值就会产生泛光
        0
    );
    composer.addPass(bloomPass);

    const mixPass = new ShaderPass(
        new THREE.ShaderMaterial({
            uniforms: {
                baseTexture: { value: null },
                bloomTexture: { value: composer.renderTarget2.texture }
            },
            vertexShader: `
            varying vec2 vUv;
                void main() {
                vUv = uv;
                gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
            }
`,
            fragmentShader: `
            uniform sampler2D baseTexture;
            uniform sampler2D bloomTexture;
            varying vec2 vUv;
            void main() {
                gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) );
            }`,
            defines: {}
        }), 'baseTexture'
    );
    mixPass.needsSwap = true;

    const outputPass = new OutputPass();

    finalComposer = new EffectComposer(renderer);
    finalComposer.addPass(ssaaRenderPass);
    finalComposer.addPass(mixPass);
    finalComposer.addPass(outputPass);
}

// 图元选中
export function select({modelOrName}){
    let model = modelOrName;
    if(typeof modelOrName === 'string'){
        model = scene.getObjectByProperty('name', modelOrName);
    }

    if(model){
        modules.pickHelper.select(model);
    }
}

/** ------------------------------------------实体解析部分-------------------------------------------------------- **/
function getColor(entity) {
    let color = options.contrastColor;//默认高对比度颜色
    if (entity.color !== undefined) color = entity.color;
    else if (data.tables && data.tables.layer && data.tables.layer.layers[entity.layer])
        color = data.tables.layer.layers[entity.layer].color;

    // 因为 scene.background = new THREE.Color(options.bgColor)，所以黑色显示时改为白色
    if (color == null || color === 0 || color === options.bgColor) {
        color = options.contrastColor;
    }
    return color;
}

function drawEntity(entity) {
    // 2023-9-6: 仅解析模型空间的实体
    if (entity.inPaperSpace) return null;

    let mesh;
    switch (entity.type) {
        case 'CIRCLE':
        case 'ARC':
            mesh = drawArc(entity);
            break;
        case 'LWPOLYLINE':
        case 'LINE':
        case 'POLYLINE':
            mesh = drawLine(entity);
            break;
        case 'TEXT':
            mesh = drawText(entity);
            break;
        case 'ATTDEF':
            mesh = drawAttdef(entity);
            break;
        case 'ATTRIB':
            mesh = drawAttrib(entity);
            break;
        case 'SOLID':
            mesh = drawSolid(entity);
            break;
        case 'POINT':
            mesh = drawPoint(entity);
            break;
        case 'INSERT':
            mesh = drawBlock(entity);
            break;
        case 'SPLINE':
            mesh = drawSpline(entity);
            break;
        case 'MTEXT':
            // console.log("实体类型 MTEXT:", entity);
            mesh = drawMtext(entity);
            break;
        case 'ELLIPSE':
            mesh = drawEllipse(entity);
            break;
        case "HATCH":
            mesh = drawHatch(entity);
            break;
        case 'DIMENSION':
            const dimTypeEnum = entity.dimensionType & 7;
            if (dimTypeEnum === 0) {
                mesh = drawDimension(entity);
            } else {
                //console.log("不支持的维度类型: " + dimTypeEnum);
            }
            break;
        default:
            // console.log("不支持的实体类型: " + entity.type, entity);
            break;
    }

    if (mesh?.material && mesh.material?.color.getHex() === options.contrastColor) {
        contrastEntity.push(mesh)
    }

    return mesh;
}

function drawArc(entity) {
    let startAngle: number, endAngle: number;
    if (entity.type === 'CIRCLE') {
        startAngle = entity.startAngle || 0;
        endAngle = startAngle + 2 * Math.PI;
    } else {
        startAngle = entity.startAngle;
        endAngle = entity.endAngle;
    }

    //@ts-ignore
    const curve = new THREE.ArcCurve(
        0, 0,
        entity.radius,
        startAngle,
        endAngle);

    const points = curve.getPoints(32);
    const geometry = new THREE.BufferGeometry().setFromPoints(points);

    const material = new THREE.LineBasicMaterial({ color: getColor(entity) });

    const arc = new THREE.Line(geometry, material);
    arc.position.x = entity.center.x;
    arc.position.y = entity.center.y;
    arc.position.z = entity.center.z;

    return arc;
}

function drawLine(entity) {
    let points: THREE.Vector3[] = [];
    let color = getColor(entity);
    let material, lineType, vertex, startPoint, endPoint,
        bulge, i, line;

    if (!entity.vertices) return; //console.log('缺少顶点的实体.');

    // 创建几何
    for (i = 0; i < entity.vertices.length; i++) {
        if (entity.vertices[i].bulge) {
            bulge = entity.vertices[i].bulge;
            startPoint = entity.vertices[i];
            endPoint = i + 1 < entity.vertices.length ? entity.vertices[i + 1] : points[0];

            let bulgePoints = getBulgeCurvePoints(startPoint, endPoint, bulge);

            points.push.apply(points, bulgePoints);
        } else {
            vertex = entity.vertices[i];
            points.push(new THREE.Vector3(vertex.x, vertex.y, 0));
        }

    }
    if (entity.shape) points.push(points[0]);


    // 设置材质
    if (entity.lineType) {
        lineType = data.tables.lineType.lineTypes[entity.lineType];
    }

    if (lineType && lineType.pattern && lineType.pattern.length !== 0) {
        material = new THREE.LineDashedMaterial({ color: color, gapSize: 4, dashSize: 4 });
    } else {
        material = new THREE.LineBasicMaterial({ linewidth: 1, color: color });
    }

    const geometry = new THREE.BufferGeometry().setFromPoints(points);

    line = new THREE.Line(geometry, material);
    return line;
}

function drawText(entity) {
    let geometry, material, text;

    if (!font)
        return console.warn('文本不支持没有Three.js字体加载的THREE.FontLoader!加载您选择的字体并将其传递给构造函数。有关更多细节，请参阅此存储库的示例或http://threejs.org/examples/?q=text#webgl_geometry_text上的Three.js示例');

    if (entity.text == null || entity.text == "") return null;

    if (entity.textHeight == null || entity.textHeight == 0) return null;

    // 当前使用的字体略宽，需要缩小一点
    // xScale: 相对 X 比例因子 — 宽度
    let fontSize = entity.xScale ? entity.xScale * entity.textHeight * 0.73 : entity.textHeight * 0.5;
    geometry = new TextGeometry(entity.text, { font: font, height: 0, size: fontSize || 100 });

    if (entity.rotation) {
        const zRotation = entity.rotation * Math.PI / 180;
        geometry.rotateZ(zRotation);
    }

    material = new THREE.MeshBasicMaterial({ color: getColor(entity) });

    text = new THREE.Mesh(geometry, material);
    text.position.x = entity.startPoint.x;
    text.position.y = entity.startPoint.y;
    text.position.z = entity.startPoint.z;

    return text;
}

function drawMtext(entity) {
    const color = getColor(entity);

    const textAndControlChars = parseDxfMTextContent(entity.text);

    //Note: 目前只支持应用于所有mtext文本的单一格式
    const content = mtextContentAndFormattingToTextAndStyle(textAndControlChars, entity, color);

    /* 单行文本渲染模式 */
    if (!font)
        return console.warn('文本不支持没有Three.js字体加载的THREE.FontLoader!加载您选择的字体并将其传递给构造函数。有关更多细节，请参阅此存储库的示例或http://threejs.org/examples/?q=text#webgl_geometry_text上的Three.js示例');
    if (content.text == null || content.text == "") return null;
    if (content.style.textHeight == null || content.style.textHeight == 0) return null;

    const geometry = new TextGeometry(content.text, { font: font, height: 0, size: content.style.textHeight || 100 });
    if (entity.rotation) {
        const zRotation = entity.rotation * Math.PI / 180;
        geometry.rotateZ(zRotation);
    }
    if (entity.directionVector) {
        const dv = entity.directionVector;
        geometry.rotateZ(new THREE.Vector3(1, 0, 0).angleTo(new THREE.Vector3(dv.x, dv.y, dv.z)));
    }
    const material = new THREE.MeshBasicMaterial({ color });
    const text = new THREE.Mesh(geometry, material);
    text.position.x = entity.position.x;
    text.position.y = entity.position.y;
    text.position.z = entity.position.z;

    return text;


    /* TODO:多行文本渲染,拉近不显示 */
    /*const txt = createTextForScene(content.text, content.style, entity, color);
    if (!txt) return null;

    console.log("MText txt:", txt);

    // const group = new THREE.Object3D();
    // group.add(txt);
    return txt;*/
}

// @ts-ignore
function drawAttdef(entity) {
    //console.log("drawAttdef:", entity);
}

// @ts-ignore
function drawAttrib(entity) {
    //console.log("drawAttrib:", entity);
}

function drawSolid(entity) {
    let material, verts,
        geometry = new THREE.BufferGeometry();

    const points = entity.points;
    // verts = geometry.vertices;
    verts = [];
    addTriangleFacingCamera(verts, points[0], points[1], points[2]);
    addTriangleFacingCamera(verts, points[1], points[2], points[3]);

    material = new THREE.MeshBasicMaterial({ color: getColor(entity) });
    geometry.setFromPoints(verts);

    return new THREE.Mesh(geometry, material);
}

function drawPoint(entity) {
    let geometry, material;

    geometry = new THREE.BufferGeometry();

    geometry.setAttribute('position', new THREE.Float32BufferAttribute([entity.position.x, entity.position.y, entity.position.z], 3));

    const color = getColor(entity);

    material = new THREE.PointsMaterial({ size: 0.1, color: new THREE.Color(color) });
    return new THREE.Points(geometry, material);
    // this.scene.add(point);
}

function drawBlock(entity) {
    if (!data.blocks) return;

    let block = data.blocks[entity.name];

    if (!block) return null;

    // 解析过的就存储起来，不再重复解析
    parsedBlocks.push(entity.name);

    if (!block.entities) return null;

    const group = new THREE.Group();

    if (entity.xScale) group.scale.x = entity.xScale;
    if (entity.yScale) group.scale.y = entity.yScale;

    if (entity.rotation) {
        group.rotation.z = entity.rotation * Math.PI / 180;
    }

    if (entity.position) {
        group.position.x = entity.position.x;
        group.position.y = entity.position.y;
        group.position.z = entity.position.z;
    }

    for (let i = 0; i < block.entities.length; i++) {
        const childEntity = drawEntity(block.entities[i]);
        if (childEntity) group.add(childEntity);
    }

    return group;
}

function drawSpline(entity) {
    if (entity.controlPoints === undefined) return null;
    const color = getColor(entity);

    const points = getBSplinePolyline(entity.controlPoints, entity.degreeOfSplineCurve, entity.knotValues, 100, undefined);

    const geometry = new THREE.BufferGeometry().setFromPoints(points);
    const material = new THREE.LineBasicMaterial({ linewidth: 1, color: color });
    return new THREE.Line(geometry, material);
}

function drawEllipse(entity) {
    const color = getColor(entity);

    const xrad = Math.sqrt(Math.pow(entity.majorAxisEndPoint.x, 2) + Math.pow(entity.majorAxisEndPoint.y, 2));
    const yrad = xrad * entity.axisRatio;
    const rotation = Math.atan2(entity.majorAxisEndPoint.y, entity.majorAxisEndPoint.x);

    const curve = new THREE.EllipseCurve(
        entity.center.x, entity.center.y,
        xrad, yrad,
        entity.startAngle, entity.endAngle,
        false, // Always counterclockwise
        rotation
    );

    const points = curve.getPoints(50);
    const geometry = new THREE.BufferGeometry().setFromPoints(points);
    const material = new THREE.LineBasicMaterial({ linewidth: 1, color: color });

    // 创建要添加到场景中的最后一个对象
    return new THREE.Line(geometry, material);
}

function drawHatch(entity) {
    if (entity.isSolid) return

    // TODO 未实现
}

function drawDimension(entity) {
    if (!data.blocks) return;

    // console.log("drawDimension", entity.block)
    const block = data.blocks[entity.block];

    // 解析过的就存储起来，不再重复解析
    parsedBlocks.push(entity.block);

    if (!block || !block.entities) return null;

    const group = new THREE.Group();
    // if(entity.anchorPoint) {
    //     group.position.x = entity.anchorPoint.x;
    //     group.position.y = entity.anchorPoint.y;
    //     group.position.z = entity.anchorPoint.z;
    // }

    for (let i = 0; i < block.entities.length; i++) {
        const childEntity = drawEntity(block.entities[i]);
        if (childEntity) group.add(childEntity);
    }

    return group;
}

/** ------------------------------------------实体解析结束-------------------------------------------------------- **/

// 设置图层可见性
export function setLayerVisible(data: { layerName: string, visible: boolean }) {
    const group = scene.getObjectByName(data.layerName);
    if (group) group.visible = data.visible;
}

// 调用modules里的方法
export function callModuleMethod(data: { moduleName: string, methodName: string }) {
    const module = modules[data.moduleName];
    if (module && module[data.methodName]) {
        module[data.methodName](data);
    }
}

// 相机复位
export function resetCamera() {
    const viewPort = camera.userData.viewPort;

    if (!viewPort) return;

    camera.left = viewPort.left;
    camera.right = viewPort.right;
    camera.top = viewPort.top;
    camera.bottom = viewPort.bottom;

    camera.position.z = 1;
    camera.position.x = viewPort.center.x;
    camera.position.y = viewPort.center.y;

    modules.drawRect.controls.target.x = camera.position.x;
    modules.drawRect.controls.target.y = camera.position.y;
    modules.drawRect.controls.target.z = 0;
    modules.drawRect.controls.object.zoom = 1;
    modules.drawRect.controls.update();
}

//let start;
export function resize({ width, height }) {
    if (!camera || data) return;

    const hscale = width / state.width;
    const vscale = height / state.height;

    state.width = width;
    state.height = height;

    camera.top = (vscale * camera.top);
    camera.bottom = (vscale * camera.bottom);
    camera.left = (hscale * camera.left);
    camera.right = (hscale * camera.right);

    camera.updateProjectionMatrix();

    renderer.setSize(width, height, false);
    composer.setSize(width, height);
    finalComposer.setSize(width, height);

    render();
}


function darkenNonBloomed(obj) {
    if (obj.material && bloomLayer.test(obj.layers) === false) {
        materials[obj.uuid] = obj.material;
        obj.material = DarkMaterial;
    }
}

function restoreMaterial(obj) {
    if (materials[obj.uuid]) {
        obj.material = materials[obj.uuid];
        delete materials[obj.uuid];
    }
}

export function render() {
    renderer.autoClear = false;

    scene.traverse(darkenNonBloomed);
    composer.render();
    scene.traverse(restoreMaterial);
    finalComposer.render();

    renderer.render(helpScene, camera);

    renderer.autoClear = true;
}

export function stopRender() {
    renderer.setAnimationLoop(null)
}

export function renderLoop() {
    renderer.setAnimationLoop(render)
}

export function helpRender() {
    renderer.autoClear = false;
    renderer.render(helpScene, camera);
}

export function dispose() {
    data = undefined;
    font = undefined;

    renderer.setAnimationLoop(null)
    renderer?.dispose();
    scene.children.forEach((obj) => {
        scene.remove(obj);
    })
    camera.remove();
    scene.remove();
}

/** ---------------------------- 设置弹窗配置变化 ---------------------------------- */
export function changeClearColor(color: 0x000000 | 0xffffff) {
    options.bgColor = color;
    options.contrastColor = options.bgColor === 0x000000 ? 0xffffff : 0x000000;
    scene.background = new THREE.Color(options.bgColor);

    contrastEntity.forEach(mesh => {
        if (!mesh.material || !mesh.material.color) return;

        mesh.material.color = new THREE.Color(options.contrastColor);
    })
}