import React, { createRef, RefObject } from 'react'
import { Color } from "csstype"
import * as Cesium from 'cesium'
import createMVTWithStyle from './mvt'
import style from './style.module.css'
import { AuxMenus, Menus } from '../auxMenu'
import { Hot, Hots } from '../../store/hots'
import { AddHot } from '../../page/hot/add'
import { ShowHot } from '../../page/hot/show'
import { toReal, toScreen, Pos2D } from './help'


declare global {
  interface Window { CESIUM_BASE_URL: any; ol: any }
}
// Cesium.defineProperties

window.CESIUM_BASE_URL = './'

const ol = window.ol

export interface LayerStyle {
  lineColor: Color,
  lineWidth: number,
  fillColor: Color
}

interface Props extends LayerStyle {
  hots: Hots
  url: string,
  lng: number,
  lat: number,
  height: number,
  show: boolean
}

interface State {
  viewer: any,
  height: number,
  mouseEvent:  React.MouseEvent | null,
  menus: Menus<string>,
  hotPos: Hot['pos'] | null,
  hotScreens: Pos2D[]
}

function createStyle (style: LayerStyle) {
  return new ol.style.Style({
    fill: new ol.style.Fill({
      color: style.fillColor,
      // stroke:"green"
    }),
    stroke: new ol.style.Stroke({
      color: style.lineColor,
      width: style.lineWidth,
      lineCap: "round",
    }),
  });
}

class VectorView extends React.Component<Props, State> {
  clipLayer: any
  domRef: RefObject<HTMLDivElement>
  downHandler: () => void

  constructor(props: Props) {
    super(props)
    this.state = { 
      hotScreens: [],
      hotPos: null,
      viewer: null, 
      height: 600,
      mouseEvent: null,
      menus: [{label: '添加热点', value: 'add-hot'}]
    }
    this.domRef = createRef()
  }

  componentDidUpdate (prevProps: Props) {
    if (!this.state.viewer || prevProps.url === this.props.url) return;
    if (this.clipLayer) {
      this.state.viewer.imageryLayers.remove(this.clipLayer, true)
    }
    if (!this.props.show) return;

    let layer = createMVTWithStyle(Cesium, ol, {
      url: this.props.url,
      style: createStyle(this.props)
    }) as any;

    this.clipLayer = this.state.viewer.imageryLayers.addImageryProvider(layer);
    this.updateScreens()
  }
  componentDidMount () {
    Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0OGQ5Y2FiZS1iNzlmLTQyNGYtYjRkMy05ODYwY2QxZjYwYTciLCJpZCI6MjE0MTQsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1Nzk1MzIwNjZ9.gcE0m9nus9WyfTvUw75j7-Mb9cuIFJnr7XHOVyTdTEg'
    let viewer = new Cesium.Viewer('cesiumContainer', {
      baseLayerPicker: false,
      geocoder: false,
      homeButton: false,
      sceneModePicker: false,
      timeline: false,
      animation: false,
      navigationHelpButton: false,
    });
    viewer.camera.flyTo({
      duration: 1,
      destination: Cesium.Cartesian3.fromDegrees(this.props.lng, this.props.lat, this.props.height)
    });
    viewer.scene.globe.baseColor = new Cesium.Color(1.0, 1.0, 1.0, 1.0);
    this.setState({ 
      viewer,
      height: this.domRef.current?.parentElement?.offsetHeight as number - 48
    })
    const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
    const moveHandler = this.updateScreens.bind(this)


    // 鼠标左键点击事件
    handler.setInputAction((event) => {
      // 鼠标移动事件
      handler.setInputAction(moveHandler, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
      handler.setInputAction(() => {
        handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_UP);
      }, Cesium.ScreenSpaceEventType.LEFT_UP);
    }, Cesium.ScreenSpaceEventType.LEFT_DOWN);
    handler.setInputAction(moveHandler, Cesium.ScreenSpaceEventType.WHEEL)
    moveHandler()
  }

  updateScreens() {
    const screens = this.props.hots.map(item => toScreen(this.state.viewer, item.pos))
    this.setState({ hotScreens: screens })
  }

  componentWillUnmount() {
    if (this.state.viewer) {
      this.clipLayer && this.state.viewer.imageryLayers.remove(this.clipLayer, true)
      this.state.viewer.destroy()
    }
  }

  render() {
    const hotEles = this.props.hots.map((hot, i) => {
      if (this.state.hotScreens[i]) {
        return <ShowHot {...hot} key={hot.id} left={this.state.hotScreens[i].x} top={this.state.hotScreens[i].y} />
      } else {
        return null
      }
    })
    if (this.state.hotScreens.length !== this.props.hots.length) {
      this.updateScreens()
    }

    return (
      <div 
        className={style.layerParent}
        onAuxClick={ev => {
          ev.persist()
          this.setState({ mouseEvent: ev })
        }}
        style={{height: this.state.height + 'px'}} 
        ref={this.domRef} 
      >
        <div id="cesiumContainer" className={style.layer}></div>
        <AuxMenus 
          onExit={() => this.setState({ mouseEvent: null })}
          menus={this.state.menus} 
          event={this.state.mouseEvent} 
          onSelect={(_, pos) => this.setState({ hotPos: toReal(this.state.viewer, pos) })} 
        />
        {this.state.hotPos && <AddHot pos={this.state.hotPos} onClose={() => this.setState({hotPos: null})} />}
        {hotEles}
      </div>
    )
  }
}

export default VectorView