 import turf_distance from '@turf/distance'
 import turf_point from 'turf-point'
 import { Fill, Stroke, Style, Text, Icon, Circle } from 'ol/style'
 import Feature from 'ol/Feature'
 import { Point, LineString } from 'ol/geom'
 import Overlay from 'ol/Overlay'
 import { Vector as VectorLayer } from 'ol/layer'
 import { Vector as VectorSource } from 'ol/source'
 import { getBottomLeft, getTopRight, containsCoordinate } from 'ol/extent'
 var _track

 function TrackOptions(config) {
     this.data = {
         id: null,
         label: null,
         icon: "http://webapi.amap.com/images/car.png",
         points: [],
         lineType: "solid",
         lineWidth: 3,
         nodeIcon: null,
         lineOpacity: 0.6,
         lineColor: "#0000ff"
     }
     this.state = {
         moveSpeed: 100,
         isSetView: true,
         syncEvent: null,
         circlable: false,
         overlayEvent: null
     }
     if (config) {
         if (config.data) {
             if (config.data.id) this.data.id = config.data.id
             if (config.data.icon) this.data.icon = config.data.icon
             if (config.data.label) this.data.label = config.data.label
             if (config.data.points) this.data.points = config.data.points
             if (config.data.lineType) this.data.lineType = config.data.lineType
             if (config.data.nodeIcon) this.data.nodeIcon = config.data.nodeIcon
             if (config.data.lineWidth) this.data.lineWidth = config.data.lineWidth
             if (config.data.lineColor) this.data.lineColor = config.data.lineColor
         }
         if (config.state) {
             if (config.state.moveSpeed) this.state.moveSpeed = config.state.moveSpeed
             if (config.state.isSetView != undefined) this.state.isSetView = config.state.isSetView
             if (config.state.syncEvent) this.state.syncEvent = config.state.syncEvent
             if (config.state.circlable != undefined) this.state.circlable = config.state.circlable
             if (config.state.overlayEvent) this.state.overlayEvent = config.state.overlayEvent
         }
     }
 }

 function trackHistory(map, option) {
     if (_track) {
         _track.stop()
     }
     try {
         var _state = option.state
         var _data = option.data
         if (option.isClearOverlay) {
             //清空
         }
         _drawLinesAndMarkers(map, _data)
         _track = new Track(map, _data.points, {
             defaultContent: _data.label,
             autoView: _state.isSetView, //是否开启自动视野调整，如果开启那么路书在运动过程中会根据视野自动调整
             speed: _state.moveSpeed,
             enableRotation: true, //是否设置marker随着道路的走向进行旋转
             circlable: _state.circlable
         })
     } catch (e) {
         console.log(e.message)
     }
 }

 function _drawLinesAndMarkers(map, data) {
     if (data.nodeIcon) {
         var image = data.nodeIcon
     }
     if (data.label) {
         var text = data.label.content
         var offset = data.label.offset
     }
     var styles = {
         'route': new Style({
             stroke: new Stroke({
                 width: 2,
                 color: '#6666aa'
             })
         }),
         'node': new Style({
             image: new Circle({
                 radius: 5,
                 stroke: new Stroke({
                     color: "#ffffff",
                     width: 2
                 }),
                 fill: new Fill({
                     color: "#000000"
                 })
             })
         }),
         'start': new Style({
             image: new Icon({
                 anchor: [0.5, 1],
                 src: image
             }),
             text: new Text({
                 font: "13px Microsoft Yahei",
                 text: "起点",
                 fill: new Fill({
                     color: "#aa3300"
                 }),
                 stroke: new Stroke({ color: "#fff", width: 2 }),
                 textAlign: "left"
             })
         }),
         'end': new Style({
             image: new Icon({
                 anchor: [0.5, 1],
                 src: image
             }),
             text: new Text({
                 font: "13px Microsoft Yahei",
                 text: "终点",
                 fill: new Fill({
                     color: "#aa3300"
                 }),
                 stroke: new Stroke({ color: "#fff", width: 2 }),
                 textAlign: "left"
             })
         }),
         'geoMarker': new Style({
             image: new Icon({
                 anchor: [0.5, 0.5],
                 rotation: 0,
                 size: [52, 26],
                 src: 'http://webapi.amap.com/images/car.png'
             }),
             text: new Text({
                 font: "13px Microsoft Yahei",
                 text: text,
                 fill: new Fill({
                     color: "#aa3300"
                 }),
                 stroke: new Stroke({ color: "#fff", width: 2 }),
                 offsetX: offset[0],
                 offsetY: offset[1],
                 textAlign: "left"
             })
         })
     }
     var vectors = []
     var style = new Style({
         stroke: new Stroke({
             width: 5,
             color: [237, 212, 0, 0.8]
         })
     })
     var lineFeature = new Feature({ geometry: new LineString(data.points), type: 'route' })
     lineFeature.setId(data.id)
         // lineFeature.setStyle(style)
     vectors.push(lineFeature)
     var arrLngLat = data.points
     var arrX = []
     var arrY = []
     for (var i = 0; i < arrLngLat.length; i++) {
         if (i > 0 && i < arrLngLat.length - 1) {
             //  var dx = arrLngLat[i + 1][0] - arrLngLat[i][0]
             //  var dy = arrLngLat[i + 1][1] - arrLngLat[i][1]
             //  var rotation = Math.atan2(dy, dx)
             var nodeMarker = new Feature({
                 type: 'node',
                 geometry: new Point(arrLngLat[i]),
             })
             vectors.push(nodeMarker)
         } else {
             if (i == 0) {
                 var starMarker = new Feature({
                     type: 'start',
                     geometry: new Point(arrLngLat[i])
                 })
                 vectors.push(starMarker)
             } else if (i == arrLngLat.length - 1) {
                 var startMarker = new Feature({
                     type: 'end',
                     geometry: new Point(arrLngLat[i])
                 })
                 vectors.push(startMarker)
             }
         }
         arrX.push(arrLngLat[i][0])
         arrY.push(arrLngLat[i][1])
     }
     var vectorLayer = new VectorLayer({
         zIndex: 5000,
         source: new VectorSource({
             features: vectors
         }),
         style: function(feature) {
             if (feature.get('type') === 'geoMarker') return null
             return styles[feature.get('type')]
         }
     })
     map.addLayer(vectorLayer)
         //标题
     var mp2 = document.createElement("div")
     mp2.id = "mycar_title"
     mp2.innerHTML = text
     var title = new Overlay({
         id: "_ty_lj_key_title",
         position: [arrX[0][0], arrY[0][1]],
         stopEvent: false,
         offset: offset,
         positioning: "bottom-left",
         element: mp2
     })
     map.addOverlay(title)
         // 地图缩放到最佳视野
     var sort1 = [arrX.sort()[0], arrX.sort()[arrX.sort().length - 1]]
     var sort2 = [arrY.sort()[0], arrY.sort()[arrY.sort().length - 1]]
     map.getView().fit([sort1[0], sort2[0], sort1[1], sort2[1]], map.getSize())
 }

 function TYCar(lnglat, config) {
     var mp = document.createElement("div")
     mp.id = "mymovecar"
     mp.style.position = "absolute"
     var mimg = document.createElement("img")
     if (config.icon) mimg.src = config.icon
     mp.appendChild(mimg)
     var TYMarker = new Overlay({
         id: "_ty_lj_key_car",
         stopEvent: false,
         offset: [-26, -13],
         positioning: "center-center",
         element: mp
     })
     TYMarker.setPosition(lnglat)
         //console.log(config)
     TYMarker.setRotation = function(a) {
         if (!isNaN(a)) {
             if (a <= 360 && a >= 0) {
                 var x = document.getElementById("mymovecar")
                 x.style.transform = "rotate(" + a + "deg)"
             }
         }
     }
     return TYMarker
 }

 function Track(map, path, opts) {
     if (!path || path.length < 1) {
         return
     }
     this.ismove = false
     this._cc = 0
     this._map = map
         //存储一条路线
     this._path = path
         //移动到当前点的索引
     this.i = 0
         //控制暂停后开始移动的队列的数组
     this._setTimeoutQuene = []
     this._opts = {
         icon: null,
         //默认速度 米/秒
         speed: 400,
         defaultContent: ''
     }
     this._setOptions(opts)
     this._rotation = 0 //小车转动的角度

     //如果不是默认实例，则使用默认的icon  instanceof BMap.Icon
     if (!this._opts.icon) {
         this._opts.icon = "http://webapi.amap.com/images/car.png"
     }

 }
 var formatLength = function(coordinates) {
         var length = 0
         let p1
         let p2
         for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) {
             p1 = turf_point(coordinates[i])
             p2 = turf_point(coordinates[i + 1])
             length += turf_distance(p1, p2)
         }
         return length
     }
     /**
      * 根据用户输入的opts，修改默认参数_opts
      * @param {Json Object} opts 用户输入的修改参数.
      * @return 无返回值.
      */
 Track.prototype._setOptions = function(opts) {
     if (!opts) {
         return
     }
     for (var p in opts) {
         if (opts.hasOwnProperty(p)) {
             this._opts[p] = opts[p]
         }
     }
 }

 /**
  * @description 开始运动
  * @param none
  * @return 无返回值.
  *
  * @example <b>参考示例：</b><br />
  * lu_track.start();
  */
 Track.prototype.start = function() {
         this.ismove = true
         const len = this._path.length
             // 不是第一次点击开始,并且小车还没到达终点
         if (this.i > 0 && this.i < len - 1) {
             // 没按pause再按start不做处理
             if (!this._fromPause) {
                 return
             } else if (!this._fromStop) {
                 //按了pause按钮,并且再按start，直接移动到下一点
                 //并且此过程中，没有按stop按钮
                 //防止先stop，再pause，然后连续不停的start的异常
                 this._moveNext(++this.i)

             }
         } else {
             //第一次点击开始，或者点了stop之后点开始
             this._addMarker()
                 //等待marker动画完毕再加载infowindow
             this._timeoutFlag = setTimeout(() => {
                 if (this._opts.defaultContent == "") {}
                 this._moveNext(this.i)
             }, 400)
         }
         //重置状态
         this._fromPause = false
         this._fromStop = false
     },
     /**
      * 结束运动
      * @return 无返回值.
      * 
      */
     Track.prototype.stop = function() {
         this.ismove = false
         this.i = 0
         this._fromStop = true
         clearInterval(this._intervalFlag)
         this._clearTimeout()
     }
     /**
      * 暂停运动
      * @return 无返回值.
      */
 Track.prototype.pause = function() {
         clearInterval(this._intervalFlag)
             //标识是否是按过pause按钮
         this._fromPause = true
         this._clearTimeout()
     }
     /**
      * 隐藏上方overlay
      * @return 无返回值.
      *
      * @example <b>参考示例：</b><br />
      */
 Track.prototype.hideInfoWindow = function() {
         this._overlay._div.style.visibility = 'hidden'
     }
     /**
      * 显示上方overlay
      * @return 无返回值.
      *
      * @example <b>参考示例：</b><br />
      */

 Track.prototype.showInfoWindow = function() {
         this._overlay._div.style.visibility = 'visible'
     }
     /**
      * 添加marker到地图上
      * @param {Function} 回调函数.
      * @return 无返回值.
      */
 Track.prototype._addMarker = function(callback) {
         if (this._marker) {
             this.stop()
             this._marker.setMap(null)
             clearTimeout(this._timeoutFlag)
         }
         //移除之前的overlay
         this._overlay && this._overlay.setMap(null)
         var marker = new TYCar(this._path[0], this._opts)
         this._map.addOverlay(marker)
         this._marker = marker
     },

     /**
      * 添加上方overlay
      * @return 无返回值. 暂时无用
      */
     Track.prototype._addInfoWin = function() {
         // var me = this
         // var overlay = new CustomOverlay(this._marker.getLngLat(), this._opts.defaultContent)
         //     //将当前类的引用传给overlay。
         // overlay.setRelatedClass(this)
         // this._overlay = overlay
         // this._map.TYaddOverLay(overlay)
     },

     /**
      * 计算两点间的距离
      * @param {Point} poi 经纬度坐标A点.
      * @param {Point} poi 经纬度坐标B点.
      * @return 无返回值.
      */
     Track.prototype._getDistance = function(pxA, pxB) {
         return formatLength([pxA, pxB])
     },
     //目标点的  当前的步长,position,总的步长,动画效果,回调
     /**
      * 移动小车
      * @param {Number} poi 当前的步长.
      * @param {Point} initPos 经纬度坐标初始点.
      * @param {Point} targetPos 经纬度坐标目标点.
      * @param {Function} effect 缓动效果.
      * @return 无返回值.
      */
     Track.prototype._move = function(initPos, targetPos, effect, currentCount) {
         this.ismove = true
             //当前的帧数
         if (!currentCount) {
             currentCount = 0
         }
         //步长，米/秒
         var timer = 200
         var step = this._opts.speed / (1000 / timer)
             //初始坐标
             //  var init_pos = this._map.getPixelFromCoordinate(initPos)
             //      //获取结束点的(x,y)坐标
             //  var target_pos = this._map.getPixelFromCoordinate(targetPos)
             //总的步长
         var count = Math.round(this._getDistance(initPos, targetPos) / step)
             //如果小于1直接移动到下一点
         if (count < 1) {
             this._moveNext(++this.i)
             return
         }
         // 两点之间匀速移动 setInterval
         this._intervalFlag = setInterval(() => {
             //两点之间当前帧数大于总帧数的时候，则说明已经完成移动
             if (currentCount >= count) {
                 clearInterval(this._intervalFlag)
                     //移动的点已经超过总的长度
                 if (this.i > this._path.length) {
                     return
                 }
                 //运行下一个点
                 this._moveNext(++this.i)
             } else {
                 currentCount++
                 this._cc = currentCount
                 var x = effect(initPos[0], targetPos[0], currentCount, count)
                 var y = effect(initPos[1], targetPos[1], currentCount, count)
                 var pos = [x, y]
                 if (currentCount == 1) {
                     var proPos = null
                     if (this.i - 1 >= 0) {
                         proPos = this._path[this.i - 1]
                     }
                     if (this._opts.enableRotation == true) {
                         this.setRotation(initPos, targetPos)
                     }
                     if (this._opts.autoView) {}
                 }
                 var extent = this._map.getView().calculateExtent(this._map.getSize())
                 var bl = getBottomLeft(extent)
                 var tr = getTopRight(extent)
                 var bb = containsCoordinate([bl[0], bl[1], tr[0], tr[1]], pos)
                     //移动中的label
                 var overs = this._map.getOverlayById("_ty_lj_key_title")
                 overs.setPosition(pos)
                 if (!bb) {
                     if (this._opts.autoView) {
                         clearInterval(this._intervalFlag)
                         this._map.getView().setCenter(pos)
                         this._move(initPos, targetPos, this._tween.linear)
                     } else {
                         this._marker.setPosition(pos)
                     }
                 } else {
                     this._marker.setPosition(pos)
                 }
             }
         }, timer)
     },

     /**
      *在每个点的真实步骤中设置小车转动的角度
      */
     Track.prototype.setRotation = function(curPos, targetPos) {
         curPos = { x: curPos[0], y: curPos[1] }
         targetPos = { x: targetPos[0], y: targetPos[1] }
         var x = Math.abs(targetPos.x - curPos.x)
         var y = Math.abs(targetPos.y - curPos.y)
         var z = Math.sqrt(x * x + y * y)
         var ration = Math.round((Math.asin(y / z) / Math.PI * 180))
         var a = 0
         if (targetPos.y < curPos.y && targetPos.x == curPos.x) {
             a = 270; // (180 - ration);
         } else if (targetPos.y > curPos.y && targetPos.x == curPos.x)
             a = 90 ///ration;
         else if (targetPos.y == curPos.y && targetPos.x < curPos.x)
             a = 180 //(180 - ration);
         else if (targetPos.y == curPos.y && targetPos.x > curPos.x)
             a = 0 //ration;
         else if (targetPos.y > curPos.y && targetPos.x > curPos.x)
             a = ration
         else if (targetPos.y > curPos.y && targetPos.x < curPos.x)
             a = 180 - ration
         else if (targetPos.y < curPos.y && targetPos.x < curPos.x)
             a = 180 + ration
         else if (targetPos.y < curPos.y && targetPos.x > curPos.x)
             a = 360 - ration
         this._marker.setRotation(a)
             //console.log(a)
         return
     },

     Track.prototype.linePixellength = function(from, to) {
         return Math.sqrt(Math.abs(from.x - to.x) * Math.abs(from.x - to.x) + Math.abs(from.y - to.y) * Math.abs(from.y - to.y))

     },
     Track.prototype.pointToPoint = function(from, to) {
         return Math.abs(from.x - to.x) * Math.abs(from.x - to.x) + Math.abs(from.y - to.y) * Math.abs(from.y - to.y)
     },

     /**
      * 移动到下一个点
      * @param {Number} index 当前点的索引.
      * @return 无返回值.
      */
     Track.prototype._moveNext = function(index) {
         this.ismove = true
         if (this._opts.func && this._opts.func != "") {
             _opts.func(index)
         }
         if (index == this._path.length - 1 && this._opts.circlable) {
             index = 0
             this.i = 0
         }
         if (index < this._path.length - 1) {
             //判断是否需要屏幕暂停，移动中心
             var ifXYZ1 = this._path[index]
             var ifXYZ2 = this._path[index + 1]
             var extent = this._map.getView().calculateExtent(this._map.getSize())
            //  var bl = getBottomLeft(extent)
            //  var tr = getTopRight(extent)
            //  tr = [this._map.getPixelFromCoordinate(tr)[0] - 30, this._map.getPixelFromCoordinate(tr)[1] + 30]
            //  bl = [this._map.getPixelFromCoordinate(bl)[0] + 30, this._map.getPixelFromCoordinate(tr)[1] - 30]
            //  tr = this._map.getCoordinateFromPixel(tr)
            //  bl = this._map.getCoordinateFromPixel(bl)
             var extentA = containsCoordinate(extent, ifXYZ1)
             var extentB = containsCoordinate(extent, ifXYZ2)
             if (extentA == false || extentB == false) {
                 if (this._opts.autoView) {
                     clearInterval(this._intervalFlag)
                     var centerA = (ifXYZ2[0] - ifXYZ1[0]) / 2 + ifXYZ2[0]
                     var centerB = (ifXYZ2[1] - ifXYZ1[1]) / 2 + ifXYZ2[1]
                     if (extentA == false && extentB == false) {
                         this._map.getView().setCenter([centerA, centerB])
                     } else if (extentA == false) {
                         this._map.getView().setCenter(ifXYZ1)
                     } else if (extentB == false) {
                         this._map.getView().setCenter(ifXYZ2)
                     } else {
                         console.log("#1005853")
                         return
                     }
                     setTimeout(() => {
                         this._move(this._path[index], this._path[index + 1], this._tween.linear)
                     }, 100)
                 } else {
                     this._move(this._path[index], this._path[index + 1], this._tween.linear)
                 }
             } else {
                 this._move(this._path[index], this._path[index + 1], this._tween.linear)
             }
         }
     },
     /**
      * 设置小车上方infowindow的内容，位置等
      * @param {Point} pos 经纬度坐标点.
      * @return 无返回值.
      */
     Track.prototype._setInfoWin = function(pos) {
         //设置上方overlay的position
         if (!this._overlay) {
             return
         }
         this._overlay.setPosition(pos, this._marker.getIcon().size)
         var index = this._troughPointIndex(pos)
         if (index != -1) {
             clearInterval(this._intervalFlag)
             this._overlay.setPosition(pos, this._marker.getIcon().getSize())
             this._pauseForView(index)
         } else {
             this._overlay.setHtml(this._opts.defaultContent)
         }
     },
     /**
      * 在某个点暂停的时间
      * @param {Number} index 点的索引.
      * @return 无返回值.
      */
     Track.prototype._pauseForView = function(index) {
         var t = setTimeout(() => { this._moveNext(++this.i) }, this._opts.landmarkPois[index].pauseTime * 1000)
         this._setTimeoutQuene.push(t)
     },
     //清除暂停后再开始运行的timeout
     Track.prototype._clearTimeout = function() {
         for (var i in this._setTimeoutQuene) {
             clearTimeout(this._setTimeoutQuene[i])
         }
         this._setTimeoutQuene.length = 0
     },
     //缓动效果
     Track.prototype._tween = {
         //初始坐标，目标坐标，当前的步长，总的步长
         linear: function(initPos, targetPos, currentCount, count) {
             var b = initPos
             var c = targetPos - initPos
             var t = currentCount
             var d = count
             return c * t / d + b
         }
     },

     /**
      * 否经过某个点的index
      * @param {Point} markerPoi 当前小车的坐标点.
      * @return 无返回值.
      */
     Track.prototype._troughPointIndex = function(markerPoi) {
         var t = this._opts.landmarkPois
         var distance
         var passedPoint = turf_point(markerPoi)
         var index = -1
         for (var i = 0, len = t.length; i < len; i++) {
             //landmarkPois中的点没有出现过的话
             if (!t[i].bShow) {
                 distance = turf_distance(passedPoint, turf_point([t[i].lng, t[i].lat]))
                     //两点距离小于10米，认为是同一个点
                 if (distance < 10) {
                     t[i].bShow = true
                     index = i
                     return
                 }
             }
         }
         return index
     }

 // 轨迹开始-----
 function start() {
     if (_track) {
         _track.start()
     }
 }
 // 轨迹停止----
 function stop() {
     if (_track) {
         _track.stop()
     }
 }

 function pause() {
     if (_track)
         _track.pause()
 }
 export default {
     trackHistory,
     start,
     stop,
     pause,
     TrackOptions
 }