import { onMount } from "solid-js";
import * as THREE from 'three';
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import * as D3 from "d3"

import json from "../../../assets/file/100000_full.json"

import utils from "../../../utils/index"
import config from "../../../base/config"

import { getMapfull } from "../../../api/bigScreen"

import "../../../assets/style/BigScreenHome.css"


class chinaMap {
    constructor(data) {
        this.$ele = data.ele;
        this.$bg = data.bg;
        this.$tooltip = data.tooltip
        this.$list = data.data;
        this.$json = data.json;
        this.$width = data.width;
        this.$height = data.height;
        this.init()
    }

    init() {
        // 墨卡托投影转换
        this.projection = D3
            .geoMercator()
            .center([108.7, 35.8])
            .scale(60)
            .translate([0, 0])
        // 第一步新建一个场景
        this.scene = new THREE.Scene();
        this.setCamera()
        this.setRenderer()
        this.generateGeometry()
        this.setController()
        this.setRaycaster()
        this.animate();
    }

    setController() {
        this.controller = new OrbitControls(
            this.camera,
            this.$ele
        )
        // 使动画循环使用时阻尼或自转 意思是否有惯性 
        this.controller.enableDamping = false;
        //是否可以缩放 
        this.controller.enableZoom = true;
        //是否自动旋转 
        this.controller.autoRotate = false;
        //是否开启右键拖拽 
        this.controller.enablePan = true;


        this.controller.maxAzimuthAngle = Math.PI / 2;
        this.controller.minAzimuthAngle = 0;
        this.controller.maxPolarAngle = Math.PI;
        this.controller.minPolarAngle = Math.PI / 2;

    }

    // 新建透视相机
    setCamera() {
        // 第二参数就是 长度和宽度比 默认采用浏览器  返回以像素为单位的窗口的内部宽度和高度
        this.camera = new THREE.PerspectiveCamera(
            50,
            this.$width / this.$height,
            1,
            1000
        )
        this.camera.position.z = 13
    }

    // 设置渲染器
    setRenderer() {
        this.renderer = new THREE.WebGLRenderer()
        // 设置画布的大小
        this.renderer.setSize(this.$width, this.$height)
        this.renderer.setClearColor("rgb(6, 30, 56)", 1)
        //这里 其实就是canvas 画布  renderer.domElement
        this.$ele.appendChild(this.renderer.domElement)
    }

    // 设置环境光
    setLight() {
        this.ambientLight = new THREE.DirectionalLight(0xffffff, 1) // 环境光
        this.scene.add(this.ambientLight)
    }

    //render 方法 
    render() {
        // 更新鼠标操作
        let clock = new THREE.Clock();
        this.controller.update(clock.getDelta());
        this.renderer.render(this.scene, this.camera)
    }

    mapData() {
        // 高亮
        // 通过摄像机和鼠标位置更新射线
        this.raycaster.setFromCamera(this.mouse, this.camera)
        // 算出射线 与当场景相交的对象有那些
        const intersects = this.raycaster.intersectObjects(
            this.scene.children,
            true
        )
        if (this.lastPick) {
            // 恢复上一次清空的
            this.lastPick.material[0].color.set(0x03f5f5)
            this.lastPick.material[1].color.set(0x03f5f5)
        }
        this.lastPick = null
        this.lastPick = (intersects.find(
            (item) => item.object.material && item.object.material.length === 2
        ) || {}).object
        if (this.lastPick) {
            this.lastPick.material[0].color.set(0xff0000)
            this.lastPick.material[1].color.set(0xff0000)
        }
        this.showTip();
    }

    animate() {
        requestAnimationFrame(this.animate.bind(this))
        this.render()
        // this.showToolTip && this.mapData()
    }

    generateGeometry() {
        // 初始化一个地图对象
        this.map = new THREE.Object3D()
        this.$list.features.forEach((elem) => {
            // 定一个省份3D对象
            const province = new THREE.Object3D()
            // 加入省份
            province.properties = elem.properties
            // 每个的 坐标 数组
            const coordinates = elem.geometry.coordinates
            // 循环坐标数组
            coordinates.forEach((multiPolygon) => {
                multiPolygon.forEach((polygon) => {
                    const shape = new THREE.Shape();
                    const lineMaterial = new THREE.LineBasicMaterial({
                        color: '#00c0eb',
                    })
                    const lineGeometry = new THREE.BufferGeometry()
                    const pointsArray = new Array()

                    for (let i = 0; i < polygon.length; i++) {
                        const [x, y] = this.projection(polygon[i])
                        const v3 = new THREE.Vector3(x, -y, 0.2);
                        const v30 = new THREE.Vector3(x, -y, 0);
                        if (i === 0) shape.moveTo(v30.x, v30.y)
                        shape.lineTo(v30.x, v30.y)
                        pointsArray.push(v3)
                    }
                    lineGeometry.setFromPoints(pointsArray)
                    const geometry = new THREE.ExtrudeGeometry(
                        shape,
                        {
                            depth: 0.2,
                            bevelOffset: -1,
                            bevelEnabled: false,
                        }
                    )
                    const material = new THREE.MeshBasicMaterial({
                        color: '#50b2d6',
                        transparent: true,
                        opacity: 0.6,
                    })
                    const material1 = new THREE.MeshBasicMaterial({
                        color: '#50b2d6',
                        transparent: true,
                        opacity: 0.5,
                    })

                    const mesh = new THREE.Mesh(geometry, [material, material1])
                    const line = new THREE.Line(lineGeometry, lineMaterial)
                    province.add(mesh)
                    province.add(line)
                })
            })
            // 添加坐标
            const centerv3 = new THREE.Vector3(elem.properties.center[0], -elem.properties.center[1], 0.2);
            console.log(elem.properties)
            this.map.add(province)

        })
        this.scene.add(this.map)
    }

    setRaycaster() {
        this.raycaster = new THREE.Raycaster()
        this.mouse = new THREE.Vector2(0, 0)
        this.$bg.addEventListener('mousemove', (event) => {
            event.preventDefault();
            !this.showToolTip && (this.showToolTip = true);
            this.mouse.x = ((event.clientX - this.$ele.getBoundingClientRect().left) / this.$width) * 2 - 1
            this.mouse.y = -((event.clientY - this.$ele.getBoundingClientRect().top) / this.$height) * 2 + 1
            // 更改div位置
            this.$tooltip.style.left = event.offsetX + 2 + 'px'
            this.$tooltip.style.top = event.offsetY + 2 + 'px'
        }, false)
    }

    showTip() {
        // 显示省份的信息
        if (this.lastPick) {
            const properties = this.lastPick.parent.properties
            this.$tooltip.textContent = properties.name
            this.$tooltip.style.visibility = 'visible'
        } else {
            this.$tooltip.style.visibility = 'hidden'
        }
    }
}

function Map(prop) {
    let $canvas = undefined, $tooltip = undefined, $bg = undefined;

    onMount(() => {
        getMapfull().then(data => {
            new chinaMap({
                ele: $canvas,
                tooltip: $tooltip,
                bg: $bg,
                height: prop.height,
                width: prop.width,
                json,
                data
            })
        })
    })
    return (
        <div className="livRang map" style={`width:${prop.width}px;`}>
            <div className="head">{prop.title}</div>
            <div ref={$bg} style="position: relative;">
                <div ref={$canvas} style={`width:${prop.width}px;height:${prop.height}px;position: relative;`}></div>
                <div ref={$tooltip} id="tooltip"></div>
            </div>
        </div>
    );
}

export default Map;
