import { LineLayer, Scene, PointLayer } from '@antv/l7';
import { GaodeMap, GaodeMapV2, Map } from '@antv/l7-maps';
import * as React from 'react';
import { ThreeLayer, ThreeRender } from '@antv/l7-three';
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';

function getImageData(img: HTMLImageElement) {
  let canvas: HTMLCanvasElement = document.createElement('canvas');
  let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
  const { width, height } = img;
  canvas.width = width;
  canvas.height = height;

  ctx.drawImage(img, 0, 0, width, height);
  const imageData = ctx.getImageData(0, 0, width, height);

  return imageData;
}

function getLatData(data: number[]) {
  const size = Math.floor(Math.sqrt(data.length));

  const arr = [];
  let startLng = 110,
    lngStep = 5 / (size - 1);
  let startLat = 30,
    latStep = -5 / (size - 1);
  for (let i = 0; i < size; i++) {
    let arr2 = [];
    for (let j = 0; j < size; j++) {
      let index = i + j * size;
      let x = startLng + lngStep * i;
      let y = startLat + latStep * j;

      arr2.push([x, y, data[index]]);
    }
    arr.push(arr2);
  }
  return arr;
}

function getLngData(data: number[]) {
  const size = Math.floor(Math.sqrt(data.length));
  const arr = [];
  let startLng = 110,
    lngStep = 5 / (size - 1);
  let startLat = 30,
    latStep = -5 / (size - 1);

  for (let i = 0; i < size; i++) {
    let arr2 = [];
    for (let j = 0; j < size; j++) {
      let index = i * size + j;
      let x = startLng + lngStep * j;
      let y = startLat + latStep * i;

      arr2.push([x, y, data[index]]);
    }
    arr.push(arr2);
  }
  return arr;
}

function getR(data: Uint8ClampedArray) {
  const arr = [];
  for (let i = 0; i < data.length; i += 4) {
    arr.push(data[i]);
  }
  return arr;
}

function setMaterial(object: any) {
  if (object.children && object.children.length && object.children.length > 0) {
    object.children.map((child: any) => setMaterial(child));
  } else if (object.material) {
    object.material.wireframe = true;
    object.material.opacity = 0.6;
  }
}

export default class GridTile extends React.Component {
  // @ts-ignore
  private scene: Scene;

  public componentWillUnmount() {
    this.scene.destroy();
  }

  public async componentDidMount() {
    const scene = new Scene({
      id: 'map',
      map: new GaodeMap({
        center: [113, 29],
        pitch: 70,
        zoom: 9,
        rotation: 180,
        style: 'blank',
        // style: 'dark',
      }),
    });
    this.scene = scene;
    scene.setBgColor('#000');

    const airPorts = [
      {
        name: '常德桃花源机场',
        lng: 111.641101,
        lat: 28.91165,
      },
      {
        name: '芷江机场',
        lng: 109.709699,
        lat: 27.442172,
      },
      {
        name: '铜仁凤凰机场',
        lng: 109.313971,
        lat: 27.880629,
      },
      {
        name: '永州零陵机场',
        lng: 111.616049,
        lat: 26.335053,
      },
      {
        name: '桂林两江国际机场',
        lng: 110.049256,
        lat: 25.210065,
      },
      {
        name: '长沙黄花国际机场',
        lng: 113.216412,
        lat: 28.183613,
      },
      {
        name: '井冈山机场',
        lng: 114.745845,
        lat: 26.852646,
      },
    ];
    const planeTarget = {
      lng2: 111.616049,
      lat2: 26.335053,
    };
    const airLineData = [
      {
        name: '常德桃花源机场',
        lng: 111.641101,
        lat: 28.91165,
        ...planeTarget,
      },
      {
        name: '芷江机场',
        lng: 109.709699,
        lat: 27.442172,
        ...planeTarget,
      },
      {
        name: '铜仁凤凰机场',
        lng: 109.313971,
        lat: 27.880629,
        ...planeTarget,
      },
      {
        name: '桂林两江国际机场',
        lng: 110.049256,
        lat: 25.210065,
        ...planeTarget,
      },
      {
        name: '长沙黄花国际机场',
        lng: 113.216412,
        lat: 28.183613,
        ...planeTarget,
      },
      {
        name: '井冈山机场',
        lng: 114.745845,
        lat: 26.852646,
        ...planeTarget,
      },
    ];

    scene.registerRenderService(ThreeRender);

    const threeJSLayer = new ThreeLayer({
      enableMultiPassRenderer: false,
      // @ts-ignore
      onAddMeshes: (threeScene, layer) => {
        threeScene.add(new THREE.AmbientLight(0xffffff));
        const sunlight = new THREE.DirectionalLight(0xffffff, 0.25);
        sunlight.position.set(0, 80000000, 100000000);
        sunlight.matrixWorldNeedsUpdate = true;
        threeScene.add(sunlight);

        // 使用 Three.js glTFLoader 加载模型
        const loader = new GLTFLoader();
        loader.load(
          'https://gw.alipayobjects.com/os/bmw-prod/3ca0a546-92d8-4ba0-a89c-017c218d5bea.gltf',
          (gltf) => {
            const antModel = gltf.scene;
            setMaterial(antModel);
            layer.adjustMeshToMap(antModel);
            layer.setMeshScale(antModel, 8000, 8000, 8000);
            layer.setObjectLngLat(antModel, [113, 29], 0);

            const animations = gltf.animations;
            if (animations && animations.length) {
              const mixer = new THREE.AnimationMixer(antModel);
              const animation = animations[1];
              const action = mixer.clipAction(animation);
              action.timeScale = 5;
              action.play();
              layer.addAnimateMixer(mixer);
            }
            antModel.rotation.y = Math.PI;
            // 向场景中添加模型
            threeScene.add(antModel);
            // 重绘图层
            layer.render();
            return '';
          },
        );
      },
    });

    scene.addImage(
      'plane',
      'https://gw.alipayobjects.com/zos/bmw-prod/96327aa6-7fc5-4b5b-b1d8-65771e05afd8.svg',
    );
    const airPrtsLayer = new PointLayer()
      .source(airPorts, {
        parser: {
          type: 'json',
          x: 'lng',
          y: 'lat',
        },
      })
      .shape('name', 'text')
      .color('rgb(22,119,255)')
      .size(10);

    const airLineLayer = new LineLayer({ blend: 'normal' })
      .source(airLineData, {
        parser: {
          type: 'json',
          x: 'lng',
          y: 'lat',
          x1: 'lng2',
          y1: 'lat2',
        },
      })
      .shape('arc3d')
      .size(1)
      .color('#f00')
      .style({
        sourceColor: 'rgb(22,119,255)',
        targetColor: 'rgba(242,246,250,0.1)',
      });

    const airPlaneLayer = new LineLayer({ blend: 'normal', zIndex: 1 })
      .source(airLineData, {
        parser: {
          type: 'json',
          x: 'lng2',
          y: 'lat2',
          x1: 'lng',
          y1: 'lat',
        },
      })
      .shape('arc3d')
      .texture('plane')
      .size(30)
      .color('#f00')
      .animate({
        duration: 0.2,
        interval: 0.2,
        trailLength: 0.2,
      })
      .style({
        textureBlend: 'replace',
        lineTexture: true, // 开启线的贴图功能
        iconStep: 6, // 设置贴图纹理的间距
      });

    fetch(
      'https://gw.alipayobjects.com/os/bmw-prod/ec5351c9-d22b-4918-ad6c-1838064d3a64.json',
    )
      .then((res) => res.json())
      .then((data) => {
        const layer = new LineLayer({})
          .source(data)
          .size(30000)
          .shape('wall')
          .style({
            opacity: 0.4,
            sourceColor: '#0DCCFF',
            targetColor: 'rbga(255,255,255, 0)',
            heightfixed: true,
          });
        scene.addLayer(layer);

        const nameLayer = new PointLayer({ zIndex: 3 })
          .source(data)
          .color('rgb(22,119,255)')
          .size(15)
          .shape('name', 'text');
        scene.addLayer(nameLayer);
      });

    const img: HTMLImageElement = new Image();
    img.crossOrigin = 'none';
    img.src =
      'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*UkvYRYS5jTAAAAAAAAAAAAAAARQnAQ';
    img.onload = function() {
      const data = getImageData(img);
      const rData = getR(data.data);
      let d1 = getLngData(rData);

      let d2 = getLatData(rData);
      const geoData = {
        type: 'FeatureCollection',
        features: [
          {
            type: 'Feature',
            properties: {},
            geometry: {
              type: 'LineString',
              coordinates: d1,
            },
          },
          {
            type: 'Feature',
            properties: {},
            geometry: {
              type: 'LineString',
              coordinates: d2,
            },
          },
        ],
      };
      const layer = new LineLayer({})
        .source(geoData)
        .size(1)
        .shape('simpleline')
        .color('rgb(22, 119, 255)')
        .style({
          vertexHeightScale: 2000,
          opacity: 0.4,
        });
      scene.addLayer(layer);
    };

    const waveLayer = new PointLayer({ zIndex: 2, blend: 'additive' })
      .source(
        [
          { lng: 113, lat: 29, size: 10000 },
          { lng: 113.5, lat: 29.5, size: 30000 },

          {
            lng: 110.23681640625,
            lat: 29.64509464986076,
            size: 74020.50373907911,
          },
          {
            lng: 115.01586914062499,
            lat: 26.88777988202911,
            size: 22908.885529976185,
          },
          {
            lng: 111.181640625,
            lat: 28.724313406473463,
            size: 73359.37302978932,
          },
          {
            lng: 112.686767578125,
            lat: 29.257648503615542,
            size: 18500.90838085843,
          },
          {
            lng: 114.664306640625,
            lat: 28.98892237190413,
            size: 20293.183968726793,
          },
          {
            lng: 113.90075683593749,
            lat: 28.17855984939698,
            size: 18051.412077639496,
          },
          {
            lng: 111.51123046875,
            lat: 27.45466493898314,
            size: 37645.94186119526,
          },
          {
            lng: 110.67626953125,
            lat: 28.004101830368654,
            size: 4214.588023703825,
          },
          {
            lng: 114.43359375,
            lat: 29.477861195816843,
            size: 61722.01580332115,
          },
          {
            lng: 110.445556640625,
            lat: 26.96124577052697,
            size: 70806.75519747598,
          },
          {
            lng: 113.75244140624999,
            lat: 27.88278388425912,
            size: 70930.24993464859,
          },
        ],
        {
          parser: {
            type: 'json',
            x: 'lng',
            y: 'lat',
          },
        },
      )
      .shape('circle')
      .color('rgb(22, 119, 255)')
      .size('size', (v) => v)
      .animate(true)
      .style({
        unit: 'meter',
      });

    const barLayer = new PointLayer({ zIndex: 2, depth: false })
      .source(
        [
          { lng: 113, lat: 29, size: 10000 },
          { lng: 113.5, lat: 29.5, size: 30000 },

          {
            lng: 110.23681640625,
            lat: 29.64509464986076,
            size: 74020.50373907911,
          },
          {
            lng: 115.01586914062499,
            lat: 26.88777988202911,
            size: 22908.885529976185,
          },
          {
            lng: 111.181640625,
            lat: 28.724313406473463,
            size: 73359.37302978932,
          },
          {
            lng: 112.686767578125,
            lat: 29.257648503615542,
            size: 18500.90838085843,
          },
          {
            lng: 114.664306640625,
            lat: 28.98892237190413,
            size: 20293.183968726793,
          },
          {
            lng: 113.90075683593749,
            lat: 28.17855984939698,
            size: 18051.412077639496,
          },
          {
            lng: 111.51123046875,
            lat: 27.45466493898314,
            size: 37645.94186119526,
          },
          {
            lng: 110.67626953125,
            lat: 28.004101830368654,
            size: 4214.588023703825,
          },
          {
            lng: 114.43359375,
            lat: 29.477861195816843,
            size: 61722.01580332115,
          },
          {
            lng: 110.445556640625,
            lat: 26.96124577052697,
            size: 70806.75519747598,
          },
          {
            lng: 113.75244140624999,
            lat: 27.88278388425912,
            size: 70930.24993464859,
          },
        ],
        {
          parser: {
            type: 'json',
            x: 'lng',
            y: 'lat',
          },
        },
      )
      .shape('cylinder')
      .color('rgb(22, 119, 255)')
      .size('size', (v) => [5, 5, v / 350])
      .animate(true)
      .style({
        opacityLinear: {
          enable: true, // true - false
          dir: 'up', // up - down
        },
        lightEnable: false,
      });

    scene.on('loaded', () => {
      scene.addLayer(waveLayer);
      scene.addLayer(barLayer);
      scene.addLayer(threeJSLayer);

      scene.addLayer(airPrtsLayer);
      scene.addLayer(airLineLayer);
      scene.addLayer(airPlaneLayer);
    });
  }

  public render() {
    return (
      <>
        <div
          id="map"
          style={{
            position: 'absolute',
            top: 0,
            left: 0,
            right: 0,
            bottom: 0,
          }}
        />
      </>
    );
  }
}
