import DTEngine, { Three } from '@tslfe/dt-engine'
import { CameraInfo, Weather, EntityType, RotateDirection, PathStyle } from '../export/BasicClass'
import { color2RGB } from './ColorTrans'
// import TacosMapEditor from "./TacosMapEditor"
// import * as THREE from 'three'
import * as TWEEN from '@tweenjs/tween.js'
/**
 * @class TacosAdapter
 * @classdesc 特斯联tacos接口类
 */
export default class TacosAdapter {
  constructor(div, url, mapping, modelPath) {
    this.div = div
    this.url = url
    this.mapping = mapping || true
    this.modelPath = modelPath
    this.cloudRender = null
    this.eventhandle = null
    this.cancelRotateFunc = null
    this.isLoadEffect = false
    this.pops = []
    this.coverings = []
    this.movingEntity = []
    this.cameraTravel = null
  }
  /**
   * 初始化地图实例
   */
  initialInstance(callback) {
    var dConfig = {
      modelPath: this.modelPath
    }
    if (window.mapconfig.lights.length > 0) {
      dConfig.theme = {
        lights: window.mapconfig.lights
      }
    }
    DTEngine.config(dConfig)
    DTEngine.render(this.div, this.url, this.mapping).then((meta) => {
      this.cloudRender = meta
      this.cloudRender.addEventListener('loaded', this.handleResponseFunction)
      // const axesHelper = new THREE.AxesHelper(100);
      // meta.scene.add(axesHelper);

      // this.getClickPosition()
      // 为图层打开所有标签
      // this.cloudRender.layer.config(params => {
      //     return {
      //         type: 'img',
      //         name: params.options.name
      //     }
      // })

      // this.mapEditor = new TacosMapEditor(meta)

      callback(this.cloudRender)
    })
  }
  /**
   * 加载场景
   * @param {string} scenename 场景名称
   * @param {function} callback 回调函数
   */
  loadScene(scenename, callback) {
    window.removeEventListener('valueChange', this.loadedEvent)

    window.sceneloaded = new CustomEvent('valueChange', {
      detail: { loaded: true, scenename: scenename }
    })

    // window.addEventListener('valueChange', this.loadedEvent.bind(this, window.sceneloaded, callback))
    window.addEventListener('valueChange', function (e) {
      callback(e)
    })
  }
  // loadedEvent (scenename, callback) {
  //     setTimeout(() => {
  //         this.cloudRender.layer.clear()
  //     }, 200);
  //     console.log('loaded:', scenename)
  //     callback(scenename)
  // }
  handleResponseFunction(total) {
    if (total.percent == 100) {
      window.dispatchEvent(window.sceneloaded)
    }
  }
  /**
   * 设置镜头参数
   * @param {CameraInfo} info 镜头参数类
   *  * {number} pitch 镜头俯仰角
   * {number} yaw 镜头偏航角
   * {array}  position 镜头位置 [x,y,z]
   * {array}  lonlat 镜头经纬度 [lon,lat,z]
   * {number} duration 镜头移动时间，单位秒
   * {number} distance 镜头离中心点的距离
   * {number} zoom 缩放级别
   */
  setCameraInfo(cameraInfo) {
    if (cameraInfo.duration == 0) {
      this.cloudRender.camera.position.set(cameraInfo.position[0], cameraInfo.position[1], cameraInfo.position[2])
      this.cloudRender.camera.setZoom(cameraInfo.zoom)
      this.cloudRender.camera.control.target.set(cameraInfo.target[0], cameraInfo.target[1], cameraInfo.target[2])
      this.cloudRender.camera.control.update()
    } else if (cameraInfo.duration > 0) {
      var pos = new Three.Vector3(cameraInfo.position[0], cameraInfo.position[1], cameraInfo.position[2])
      var targ = new Three.Vector3(cameraInfo.target[0], cameraInfo.target[1], cameraInfo.target[2])
      this.cloudRender.camera.flyToPosition(pos, targ, cameraInfo.duration)
    }
  }
  setCameraLimit(pitch, yaw, boundingBox, minDistance, maxDistance) {
    // 远近缩放距离
    this.originMinDis = this.cloudRender.camera.control.minDistance
    this.originMaxDis = this.cloudRender.camera.control.maxDistance
    this.cloudRender.camera.control.minDistance = minDistance
    this.cloudRender.camera.control.maxDistance = maxDistance
  }
  removeCameraLimit() {
    this.cloudRender.camera.control.minDistance = this.originMinDis
    this.cloudRender.camera.control.maxDistance = this.originMaxDis
  }
  /**
   * 获得镜头参数
   * @returns CameraInfo 镜头参数
   */
  getCameraInfo() {
    return new Promise((resolve, reject) => {
      this.cloudRender.camera.control.saveState()
      resolve(
        new CameraInfo(
          0,
          0,
          this.cloudRender.camera.position,
          null,
          0,
          0,
          this.cloudRender.camera.zoom,
          this.cloudRender.camera.control.target
        )
      )
    })
  }

  pointerDown(event, that) {
    if (event.isPrimary === false) return
    var pos = { x: 0, y: 0, z: 0 }
    var mouse = new THREE.Vector2()
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
    var raycaster = new THREE.Raycaster()
    raycaster.setFromCamera(mouse, that.cloudRender.camera)
    const intersects = raycaster.intersectObject(that.cloudRender.scene, true)

    if (intersects.length > 0) {
      const selected = intersects[0]
      pos = { x: selected.point.x, y: selected.point.y, z: selected.point.z }
      // if (selected.object.type == "Sprite") {
      //     console.log('click sprite:', selected)
      // }
    }
    return pos
  }
  /**
   * 设置镜头绕场景中心点旋转
   * @param {number} time 旋转一周所需要的时间,单位秒
   * @param {RotateDirection} direction 旋转方向，clockwise:顺时针; anticlockwise:逆时针; stop:停止旋转
   * @returns 成功、失败回调
   */
  setCameraRotate(time = null, direction, speed) {
    return new Promise((resolve, reject) => {
      if (direction == RotateDirection.Stop) {
        this.cancelRotateFunc()
      } else {
        this.cancelRotateFunc = this.cloudRender.camera.fit(null, { speed: speed })
      }
      resolve()
    })
  }
  /**
   * 镜头聚焦物体
   * @param {string} id 聚焦目标的 id
   * @param {number} distance 距离，单位米
   * @param {EntityType} type 物体类型
   */
  focusEntity(id, distance, type, isFlashing) {
    return new Promise((resolve, reject) => {
      this.cloudRender.context.components
        .getModel(id)
        .then((m) => {
          if (m.length > 0) {
            m.focus({
              autoAdjust: true,
              distance: distance || 5
              // phi: 0,
              // theta: -10
            })
            if (isFlashing) {
              m.selected = true
            }
            resolve()
          }
        })
        .catch((err) => {
          reject(err)
        })
      // var m = this.cloudRender.get(id)
      // m.focus({
      //     autoAdjust: true,
      //     distance: distance || 5,
      //     // phi: 0,
      //     // theta: -10
      // })
      // if (isFlashing) {
      //     m.selected = true
      // }
      // resolve()
    })
  }
  /**
   * 销毁实体
   * @param {string} id 需要销毁的实体id
   * @param {EntityType} type 物体类型
   * @returns 成功、失败回调
   */
  destroyEntity(id, type) {
    // var m = this.cloudRender.scene.getObjectByName(id)
    // var parent = m.parent
    // parent.remove(m)
    return new Promise((resolve, reject) => {
      if (type == EntityType.Path || type == EntityType.POI || type == EntityType.Effect) {
        var p = this.coverings.findIndex((item) => {
          if (item.id == id) {
            return true
          }
        })
        if (p > -1) {
          var sub = this.coverings[p].subtype
          if (sub) {
            if (sub == 'flame') {
              this.cloudRender.effect.clearFlame()
            }
            if (sub == 'smoke') {
              this.cloudRender.effect.clearSmoke()
            }
          } else {
            this.coverings[p].element()
            this.coverings.splice(p, 1)
          }
          resolve()
        }
        // var that = this
        // this.cloudRender.context.components.getModel(id).then((m) => {
        //     that.cloudRender.layer.toggle(m)
        //     resolve()
        // }).catch((err) => {
        //     reject(err)
        // })
      } else if (type == EntityType.HeatMap) {
        this.cloudRender.effect.clearHeatMap()
      } else if (type == EntityType.Object) {
        this.cloudRender.context.components
          .getModel(id)
          .then((m) => {
            m.dispose()
            resolve()
          })
          .catch((err) => {
            reject(err)
          })
      }
    })
  }
  /**
   * 高亮实体
   * @param {string} id 高亮实体id
   * @param {array} borderColor 高亮实体边颜色[r,g,b]
   */
  highlightEntity(id, borderColor) {
    return new Promise((resolve) => {
      var c = color2RGB(borderColor)
      this.cloudRender.composer.passes[1].visibleEdgeColor.set(c)
      var that = this

      this.cloudRender.context.components.getModel(id).then((m) => {
        if (m.length > 0) {
          that.cloudRender.composer.passes[1].selectedObjects.push(m[0].model)
          resolve()
        }
      })
    })
  }
  /**
   * 取消高亮实体
   * @param {string} id 取消高亮实体id
   */
  restoreEntity(id) {
    return new Promise((resolve) => {
      var that = this
      this.cloudRender.composer.passes[1].visibleEdgeColor.set('#ef790b')
      this.cloudRender.context.components.getModel(id).then((m) => {
        var s = []
        that.cloudRender.composer.passes[1].selectedObjects.forEach(
          (element) => element != m[0].model && s.push(element)
        )
        that.cloudRender.composer.passes[1].selectedObjects = s
        resolve()
      })
    })
  }
  /**
   * 隐藏实体
   * @param {string} id 隐藏实体id
   */
  hideEntity(id) {
    return new Promise((resolve) => {
      this.cloudRender.context.components.getModel(id).then((m) => {
        if (m.length > 0) {
          m.visible = false
          resolve()
        }
      })
    })
  }
  /**
   * 显示实体
   * @param {string} id 显示实体id
   */
  showEntity(id) {
    return new Promise((resolve) => {
      this.cloudRender.context.components.getModel(id).then((m) => {
        m.visible = true
        resolve()
      })
    })
  }

  /**
   * 设置环境时间
   * @param {int} datetime 时间戳
   */
  setDateTime(date) {
    var d = new Date(date * 1000)
    var h = d.getHours()
    if (!this.isLoadEffect) {
      this.cloudRender.loadEffect()
      this.isLoadEffect = true
    }
    if (h >= 6 && h <= 18) {
      this.cloudRender.environment.dayTime()
    } else {
      this.cloudRender.environment.nightTime()
    }
  }
  /**
   * 设置天气
   * @param {Weather} name 天气
   */
  setWeather(weather) {
    if (!this.isLoadEffect) {
      this.cloudRender.loadEffect()
      this.isLoadEffect = true
    }
    this.cloudRender.environment.clear()
    switch (weather) {
      // case Weather.晴天: break;
      // case Weather.阴天: break;
      case Weather.小雨:
        this.cloudRender.environment.raining(1)
        break
      case Weather.中雨:
        this.cloudRender.environment.raining(3)
        break
      case Weather.大雨:
        this.cloudRender.environment.raining(5)
        break
      case Weather.小雪:
        this.cloudRender.environment.snowing(1)
        break
      case Weather.中雪:
        this.cloudRender.environment.snowing(3)
        break
      case Weather.大雪:
        this.cloudRender.environment.snowing(5)
        break
      // case Weather.雾霾: break;
      // case Weather.少云: break;
      default:
        this.cloudRender.environment.clear()
        break
    }
  }
  startThirdPersonRoaming(duaration, speed, loop, armDistance, roll, pitch, yaw, path) {
    var md = null
    if (loop) {
      md = loop ? 'loop' : 'reverse'
    }
    this.cameraTravel = this.cloudRender.camera.travel(path, {
      easing: TWEEN.Easing.Linear.None,
      time: duaration || 5000,
      autoAdjust: false,
      mode: md,
      distance: armDistance || 10
    })
  }
  pauseThirdPersonRoaming() {
    if (this.cameraTravel) {
      this.cameraTravel.stop()
    }
  }
  continueThirdPersonRoaming() {
    if (this.cameraTravel) {
      this.cameraTravel.continue()
    }
  }
  stopThirdPersonRoaming() {
    if (this.cameraTravel) {
      this.cameraTravel.stop()
    }
  }
  /**
   * 添加POI点，图片或者文字
   * @param {POI} poidata
   * POI数据
   *  * {string} id 唯一标识
   * {string} resourceName 资源库中资源名称
   * {number[]} position POI位置[x,y,z]
   * {number[]} scale x,y,z方向缩放比例
   * {string} label POI文字
   * iconUrl POI图标url
   * {number[]} offset 偏移量[x,y,z]
   */
  addPOI(poidata) {
    if (poidata.label != '') {
      var remove = this.cloudRender.layer.label(poidata.label, {
        type: 'text',
        position: poidata.position,
        fontsize: 16,
        scale: poidata.scale.slice(0, 1) || 0.3,
        offset: poidata.iconOffset || [0, 0, 0],
        userData: poidata.id,
        sizeAttenuation: false,
        line: {
          type: 'solid'
          // width: number;
          // color: string;
          // dashSize: number;
          // gapSize: number;
        }
      })
      this.coverings.push({ id: poidata.id, element: remove, type: EntityType.POI })
    } else if (poidata.iconUrl != '') {
      var remove = this.cloudRender.layer.label(poidata.iconUrl, {
        type: 'image',
        position: poidata.position,
        scale: poidata.scale.slice(0, 1) || 0.25,
        size: poidata.scale.slice(0, 1) || [0.4, 0.4],
        offset: poidata.offset || [0, 0, 0],
        userData: poidata.id,
        sizeAttenuation: false,
        line: {
          type: 'solid'
        }
      })
      this.coverings.push({ id: poidata.id, element: remove, type: EntityType.POI })
    }
  }
  /**
   * 根据id获取实体信息
   * @param {string} id 实体id
   * @returns 实体信息
   */
  getEntityByID(id) {
    return this.cloudRender.get(id)
  }
  /**
   * 场景内所有实体id
   * @returns 场景内所有实体id
   */
  getAllEntityIds() {
    var ids = []
    var s = this.cloudRender.scene
    s.traverse((child) => {
      if (child.isObject3D) {
        ids.push(child.name)
      }
    })
    return ids
  }
  /**
   * 创建热力图
   * @param {string} id 热力图id
   * @param {number} radius 热力半径，单位米
   * @param {array} minCoord 区域最小坐标 [x,y,z]
   * @param {array} maxCoord 区域最大坐标 [x,y,z]
   * @param {array} data 位置与数据，[x,y,z,value]
   */
  createHeatmap(id, radius, minCoord, maxCoord, data) {
    if (!this.isLoadEffect) {
      this.cloudRender.loadEffect()
      this.isLoadEffect = true
    }
    var hdata = data.map((item) => {
      return {
        position: [item[0], item[1], item[2]],
        value: item[3],
        radius: radius
      }
    })
    return new Promise((resolve) => {
      var remove = this.cloudRender.effect.createHeatMap(hdata, {
        maxValue: 5, // 热力最大值
        colors: ['transparent', 'green', 'yellow', 'red'], //色环
        segments: 8, // 粒子数比例
        opacity: 1 // 粒子透明度
      })
      // this.coverings.push({ id: id, element: remove, type: EntityType.HeatMap })
      resolve()
    })
  }
  /**
   * 创建弹窗
   * @param {string} poiId 需要创建弹窗的实体id
   * @param {string} windowID 创建弹窗的id
   * @param {string} windowUrl 弹窗内容html地址
   * @param {number} width 窗口宽，单位像素
   * @param {number} height 窗口高，单位像素
   * @param {number} xoffset 弹窗左上角相对横向偏移量，单位像素
   * @param {number} yoffset 弹窗左上角相对纵向偏移量，单位像素
   */
  addInfowindow(poiID, windowID, windowUrl, width, height, xOffset, yOffset, type = null) {
    return new Promise((resolve) => {
      var m = this.cloudRender.get(poiID)
      if (m) {
        var mainCon = document.getElementById(this.div)
        var container = document.createElement('div')
        container.setAttribute('id', windowID)
        mainCon.appendChild(container)
        container.innerHTML = windowUrl
        var pwin = m.html(windowID, {
          display: 'auto',
          // chain: true,
          line: {
            type: 'solid'
          },
          offset: [xOffset, yOffset, 50]
        })
        this.pops.push({ id: poiID, pop: pwin })
      }
      resolve(pwin)
    })
  }
  destroyInfowindow(poiId, windowID, type) {
    return new Promise((resolve) => {
      var p = this.pops.findIndex((item) => {
        if (item.id == poiId) {
          return true
        }
      })
      if (p > -1) {
        this.pops[p].pop()
        this.pops.splice(p, 1)
      }
      resolve()
    })
  }
  /**
   *楼层展开
   * @param {string} buildingId 需要展开的建筑id
   * @param {array} floorIds 需要展开的楼层url
   * @param {number} space 展开后楼层间间隔距离，单位米
   * @param {number} floor 楼层号
   */
  explodeEntity(buildingId = null, floorIds, space = null, floor = null) {
    var that = this
    return new Promise((resolve) => {
      that.cloudRender.enter(floorIds[0], 'url', true).then((e) => {
        resolve()
      })
    })
  }
  /**
   * 楼层还原
   * @param {string} buildingId 需要展开的建筑url
   * @param {array} floorIds
   */
  unexplodedEntity(buildingId, floorIds = null) {
    var that = this
    return new Promise((resolve) => {
      that.cloudRender.enter(buildingId, 'url', true).then((e) => {
        resolve()
      })
    })
  }
  /**
   * 添加模型实体
   * @param {string} id 模型实体id
   * @param {array} position 位置 [x,y,z]
   * @param {string} resourceName  资源库中资源的名称
   * @param {number} roll 翻滚角
   * @param {number} pitch 俯仰角
   * @param {number} yaw 偏航角
   * @param {array} scale 比例 [scaleX,scaleY,scaleZ]
   */
  addModel(id, position, resourceName, roll, pitch, yaw, scale) {
    var that = this
    this.cloudRender.createComponent(resourceName).then((m) => {
      m.id = id
      m.position = position
      m.scale = scale || [1, 1, 1]
      that.cloudRender.add(m)
    })
  }
  startEntityMoving(id, duration, speed = null, loop, path, roll, pitch, yaw) {
    var md = null
    if (loop) {
      md = loop ? 'loop' : 'reverse'
    }
    var entity = this.cloudRender.get(id)
    var mEnty = entity.moveTo(path, {
      time: duration || 7000,
      mode: md,
      easing: TWEEN.Easing.Linear.None
    })
    this.movingEntity.push({ id: id, mEntity: mEnty })
  }
  pauseEntityMoving(id) {
    var p = this.movingEntity.findIndex((item) => {
      if (item.id == id) {
        return true
      }
    })
    if (p > -1) {
      this.movingEntity[p].mEntity.stop()
    }
  }
  resumeEntityMoving(id) {
    var p = this.movingEntity.findIndex((item) => {
      if (item.id == id) {
        return true
      }
    })
    if (p > -1) {
      this.movingEntity[p].mEntity.continue()
    }
  }
  stopEntityMoving(id) {
    var p = this.movingEntity.findIndex((item) => {
      if (item.id == id) {
        return true
      }
    })
    if (p > -1) {
      this.movingEntity[p].mEntity.stop()
    }
  }
  /**
   * 创建特效
   * @param {string} id 特效id
   * @param {string} resourceName 资源库中资源的名称
   * @param {array} position 特效位置，[x,y,z]
   * @param {number} roll 翻滚角
   * @param {number} pitch 俯仰角
   * @param {number} yaw 偏航角
   * @param {array} scale 比例 [scaleX,scaleY,scaleZ]
   */
  addEffect(id, resourceName, position, roll, pitch, yaw, scale) {
    if (!this.isLoadEffect) {
      this.cloudRender.loadEffect()
      this.isLoadEffect = true
    }
    // 加火焰
    if (resourceName == '火焰') {
      var remove = this.cloudRender.effect.createFlame({
        radius: 3 || 3 * Math.max(scale[0], scale[1]), // 火焰半径
        height: 10 || 10 * scale[2], // 火焰高度
        color: '#ff0000', // 火焰颜色
        density: 10000, // 火焰密度
        position: position // 火焰位置
      })
      this.coverings.push({ id: id, element: remove, type: EntityType.Effect, subtype: 'flame' })
    } else if (resourceName == '烟雾') {
      var remove = this.cloudRender.effect.createSmoke({
        size: 1 || 1 * Math.max(scale[0], scale[1]), // 烟雾大小
        width: 1 || 1 * scale[1], // 烟雾宽度
        height: 1 || 1 * scale[2], // 烟雾高度
        colors: ['#111111', '#222222', '#333333', '#66ccff', '#66ccff', '#66ccff'], // 烟雾颜色,从下到上,最多传6个
        position: position // 烟雾位置
      })
      this.coverings.push({ id: id, element: remove, type: EntityType.Effect, subtype: 'smoke' })
    }
  }
  add3dText() {}

  addPath(id, path, pathStyle, color, width) {
    var dashed = false
    switch (pathStyle) {
      case PathStyle.Dashed:
        dashed = true
        break
      case PathStyle.Solid:
      default:
        dashed = false
        break
    }
    var c = color2RGB(color)
    let navigator = this.cloudRender.navigator

    var road = navigator.create({
      color: c || '#00ffee',
      dashed: dashed,
      labelSize: width || 3,
      duration: 3
      // openStatus: true,
    })

    var hdata = path.map((item) => {
      return new THREE.Vector3(item[0], item[1], item[2])
    })
    road.go(hdata)
    var sr = { id: id, element: road, type: EntityType.Path }
    this.coverings.push(sr)
    return sr
  }

  addArea() {}
  destroyMap() {
    if (this.cloudRender) {
      this.cloudRender.dispose()
    }
  }
  addEventListener(eventType, callback) {
    this.eventhandle = function (obj) {
      callback(obj)
    }
    this.cloudRender.addEventListener(eventType, this.eventhandle)
  }
  removeEventListener(eventType) {
    this.cloudRender.removeEventListener(eventType, this.eventhandle)
  }
  _disableSelectScene() {
    if (!this.cloudRender) {
      return
    }
    for (var i = 0; i < this.cloudRender.context.components.children.length; i++) {
      this.cloudRender.context.components.children[i].disabled = true
    }
  }
  _enableSelectScene() {
    if (!this.cloudRender) {
      return
    }
    for (var i = 0; i < this.cloudRender.context.components.children.length; i++) {
      this.cloudRender.context.components.children[i].disabled = false
    }
  }
  // getClickPosition (callback) {
  //     window.removeEventListener('pointerdown', this.pointerDownListener)
  //     var that = this
  //     var pos = { x: 0, y: 0, z: 0 }
  //     // return new Promise((resolve) => {
  //     window.addEventListener('pointerdown', this.pointerDownListener = function (event) {
  //         pos = that.pointerDown(event, that)
  //         callback(pos)
  //         // console.log(pos)
  //         // resolve(pos)
  //     })
  //     // })
  // }
}
