<template>
  <div class="trajectory">
    <div class="trajectory-con">
      <div class="top">
        <van-nav-bar title="历史轨迹" left-arrow @click-left="onNavBack" left-text="返回" />
        <!-- 右边固定的时间选项 -->
        <div class="time-picker" :style="{ width: `${timePickWidth}%` }">
          <div class="time-picker-left" :style="{ width: `${timeWidth}%` }" @click="onTimeClick">
            <van-icon name="arrow-left" v-if="isLeft" />
            <van-icon name="arrow" v-if="!isLeft" />
            <span>时间</span>
          </div>
          <div class="time-picker-right" v-if="isPopup">
            <span @click="onStartClick" v-show="true">{{ initTimePick.initStartTime }}</span>
            <label class="labelTime">至</label>
            <span @click="onEndClick" v-show="true">{{ initTimePick.initEndTime }}</span>
            <van-datetime-picker
              v-model="timePickData.selectStartTime"
              v-show="timePickData.timePickStartShow"
              class="datetimePicker"
              type="time"
              title="选择开始时间"
              :min-hour="timePickData.defaultStartTime.slice(0, 2)"
              :max-hour="timePickData.defaultEndTime.slice(0, 2)"
              confirm-button-text="确定"
              @confirm="onStartTimeConfirm"
              @cancel="onStartTimeCancel"
              :item-height="itemHeight"
            />
            <van-datetime-picker
              v-model="timePickData.selecttEndTime"
              v-show="timePickData.timePickEndShow"
              class="datetimePicker"
              type="time"
              title="选择结束时间"
              :min-hour="timePickData.defaultStartTime.slice(0, 2)"
              :max-hour="timePickData.defaultEndTime.slice(0, 2)"
              @confirm="onEndTimeConfirm"
              confirm-button-text="确定"
              @cancel="onEndTimeCancel"
              :item-height="itemHeight"
            />
          </div>
          <div class="time-picker-right-confirm" @click="onConfirm" v-if="isPopup">
            <div class="right-confirm-text">
              <span>查看</span>
            </div>
          </div>
        </div>
        <div class="dateArea">
          <i class="left active" @click="dateClick"></i>
          <span @click="dateAreaClick">{{ new Date(date).Format('yyyy年MM月dd日') }}</span>
          <i :class="['right', { active: count < 0 }]" @click="dateClick('add')"></i>
        </div>
        <div class="calendar" v-show="calendarShow">
          <van-calendar
            v-model="calendarShow"
            :min-date="minDate"
            :max-date="maxDate"
            :default-date="defaultDate"
            :round="false"
            :poppable="false"
            :show-confirm="false"
            :show-title="false"
            :show-subtitle="false"
            @select="onSelect"
          />
        </div>
      </div>
      <!-- 轨迹地图部分 -->
      <div id="trajectory_map" class="index_map" style="width: 100%; height: 100vh"></div>
      <!-- 底部部分 -->
      <div class="bottom">
        <div class="conArea" v-show="bottomContentShow">
          <!-- 右边的速度滑块 -->
          <div class="slider-bar">
            <!--<span>速度</span>-->
            <span>慢</span>
            <div class="bar">
              <van-slider :min="min" :max="max" :step="step" v-model="leftCode" vertical />
            </div>
            <!--<div>{{leftCode}}</div>-->
            <!--<div>km/h</div>-->
            <span>快</span>
          </div>
          <!-- 下面的地址  时间 -->
          <div class="con">
            <span
              class="title"
              v-if="
                decoratedAddressList === null || (decoratedAddressList !== null && decoratedAddressList.length === 0)
              "
              >暂无地址信息</span
            >
            <div class="content-list" v-if="decoratedAddressList !== null && decoratedAddressList.length > 0">
              <div class="content-item" v-for="(item, index) in decoratedAddressList" :key="index">
                <p class="title">{{ item.address ? item.address + '(附近)' : '暂无位置信息' }}</p>
                <div class="states">
                  <span v-if="item.s_time != item.repeat_last_time">
                    {{ item.s_time.split(' ')[1] }}
                    ~
                    {{ item.repeat_last_time.split(' ')[1] }}
                  </span>
                  <span v-if="item.s_time == item.repeat_last_time">
                    {{ item.time.split(' ')[1] }}
                  </span>
                </div>
              </div>
            </div>
          </div>
          <!-- 播放按钮 -->
          <div class="player">
            <van-icon name="play-circle-o" v-show="!playFlag" @click="onPlay" />
            <van-icon name="pause-circle-o" v-show="playFlag" @click="onPause" />
          </div>
        </div>
        <!--<overlay-loading :showOverlay="showOverlay"></overlay-loading>-->
      </div>
    </div>
  </div>
</template>

<script>
import MapLoader from '@/common/amap.js';
import DialogService from '../../services/dialog-service';
import ToastService from '../../services/toast-service';
import { ErrorAMapMsgModel } from '../../config/models';
import APIDevice from '../../api/device';

export default {
  data() {
    const ms_TO_kmh = 3.6;
    return {
      ms_TO_kmh: ms_TO_kmh,
      showOverlay: true,
      lineArr: [],
      lineArrCopy: [],
      allLineArr: [],
      //                map: null,
      marker: null,
      playFlag: false, //播放状态
      count: 0, //日期count
      date: this.$own.getNowFormatDate(0),
      clickFlag: true, //左右日期按钮是否给予点击
      bottomContentShow: true,
      address: '',
      time: '',
      calendarShow: false,
      minDate: /* new Date(2020, 0, 1) */ new Date(
        this.$dayjs()
          .month(this.$dayjs().month() - 1)
          .hour(0)
          .minute(0)
          .second(0)
          .format()
      ),
      maxDate: /* new Date() */ new Date(this.$dayjs().hour(0).minute(0).second(0).format()),
      defaultDate: /* new Date() */ new Date(this.$dayjs().hour(0).minute(0).second(0).format()),
      num: 0,
      playState: 'off',
      max: 8000,
      min: 100,
      leftCode: 100,
      step: 100,
      map: {
        instance: null,
        position: null,
        zoom: 15,
        marker: null,
        markerNew: null,
        polyline: null,
        polylineNew: null,
        passedPolyline: null,
        passedPolylineNew: null,
        graspRoad: null,
        walking: null,
        riding: null,
        transfer: null,
        city: null
      },
      speedTypes: {
        // 步行1m/S；骑车3m/S；汽车11m/S~16m/S；高铁16m/S~80m/S
        walking: 1.7 * ms_TO_kmh,
        riding: [1.7 * ms_TO_kmh, 6.6 * ms_TO_kmh],
        driving: [6.6 * ms_TO_kmh, 16.7 * ms_TO_kmh],
        //                    highRailway: [ 16.8 * ms_TO_kmh, 80 * ms_TO_kmh ],
        highRailway: [16.8 * ms_TO_kmh, 55.5 * ms_TO_kmh]
      },
      serviceTypes: {
        walking: 'walking',
        riding: 'riding',
        driving: 'driving',
        transfer: 'transfer',
        overTime: 'overTime',
        overSpeed: 'overSpeed',
        sameAddress: 'sameAddress'
      },
      dataList: [],
      path: [],
      polylineList: [],
      lngLatOnMoving: [],
      movingIndexOfPolylineList: 0,
      circleList: [],
      limitDistance: 50, // 聚集点距离
      limitSecond: 60 * 6, // 相邻点的时间差（作为直连线/上报缺点的依据）
      limitSpeed: 120, // km/h 超速（直连线）
      thresholdTime: 60 * 15, // 15 分钟；判断两个 driving 时间差是否符合该阀值
      decoratedAddressList: null,
      collectionStraightPoints: [], // 直连线的点的记录
      isPopup: false, //右上快捷时间选择器是否显示
      timePickWidth: 20, //时间选择器初始的百分比宽度
      timeWidth: 100, //时间选择器最大的百分比宽度
      isLeft: true, //时间选择器是否在左边.默认在左边
      itemHeight: Number(((document.body.clientWidth / 750) * 75).toFixed()), //时间选择器item的高度
      timePickData: {
        defaultStartTime: '00:00',
        defaultEndTime: '23:59',
        timePickStartShow: false,
        timePickEndShow: false,
        selectStartTime: '00:00',
        selecttEndTime: '23:59'
      }, //时间选择器
      initTimePick: {
        initStartTime: '00:00',
        initEndTime: '23:59'
      }, //初始化接口第一次获取的时间
      dialogShow: false, //轨迹对比弹窗是否显示
      dialogInput: '', //弹窗输入的json数据
      dataListNew: [],
      pathNew: [],
      polylineListNew: [],
      lngLatOnMovingNew: [],
      collectionStraightPointsNew: [],
      circleListNew: [],
      isProduction: process.env.NODE_ENV === 'production'
    };
  },
  mounted() {
    //            this.getAmap();

    this.getMap();
    this.toggleBottom(true);
  },
  methods: {
    onNavBack() {
      this.$router.push({
        name: 'location'
      });
    },
    onPlay() {
      if (this.$own.isNull(this.polylineList)) {
        ToastService.fail({ message: '暂无信息' });
        return;
      }
      this.map.marker.moveAlong(this.polylineList, this.leftCode);
      console.log('dataList:::', this.dataList);
    },
    onPause() {
      this.map.marker.pauseMove();
    },
    // 去重、补上【开始时间、结束时间、重复项】
    deduplicatedANDDecorateList(dataList) {
      let result = [],
        repeatNum = 1;
      for (let i = 0; i < dataList.length; i++) {
        let preItem = dataList[i - 1 >= 0 ? i - 1 : 0];
        const currentItem = dataList[i];
        if (typeof currentItem === 'object' && Array.isArray(currentItem)) {
          // 兼容纯经纬度数组
          if (i === 0) {
            result.push(preItem);
            continue;
          }
          if (
            currentItem[0] === 0 ||
            currentItem[1] === 0 ||
            (currentItem[0] === preItem[0] && currentItem[1] === preItem[1])
          ) {
            result[result.length - 1] = currentItem;
          }
        } else {
          // 对象数组
          if (i === 0) {
            result.push({
              ...preItem,
              s_time: preItem.time.replace(new RegExp(/(-)/g), '/'),
              e_time: preItem.time.replace(new RegExp(/(-)/g), '/'),
              repeat_last_time: preItem.time.replace(new RegExp(/(-)/g), '/'),
              repeatNum: repeatNum
            });
            continue;
          }
          let last = result[result.length - 1];
          if (
            currentItem.lng === 0 ||
            currentItem.lat === 0 ||
            (currentItem.lng === preItem.lng && currentItem.lat === preItem.lat)
          ) {
            last = {
              ...last,
              //                                s_time: last.s_time,
              //                                e_time: last.time,
              repeat_last_time: currentItem.time.replace(new RegExp(/(-)/g), '/'), //正则 接口返回的时间数据（yyyy-MM-dd）ios系统不能识别,所以我们将它-变成/ (yyyy/MM/dd)
              repeatNum: ++repeatNum,
              distance: last.distance
            };
            result[result.length - 1] = last;
          } else {
            repeatNum = 1;
            const d = this.calculateDistanceByPoints([last.lng, last.lat], [currentItem.lng, currentItem.lat]);
            result.push({
              ...currentItem,
              s_time: currentItem.time.replace(new RegExp(/(-)/g), '/'),
              e_time: currentItem.time.replace(new RegExp(/(-)/g), '/'),
              repeat_last_time: currentItem.time.replace(new RegExp(/(-)/g), '/'),
              repeatNum: repeatNum,
              distance: d
            });
          }
        }
      }
      return result;
    },
    // 米
    calculateDistanceByPoints(s_lngLat, e_lngLat) {
      // eslint-disable-next-line
      return parseInt(AMap.GeometryUtil.distance(s_lngLat, e_lngLat));
    },
    // 筛选出聚集点
    decorateListCircle(dataList) {
      try {
        if (this.$own.isNull(dataList)) return [];
        if (dataList.length === 1) return [{ ...dataList[0], circle: false, clusterSize: 1 }];
        let result = [];
        let stack = [];
        for (let i = 0; i < dataList.length; i++) {
          const current = dataList[i];
          if (current.distance < this.limitDistance) {
            // 成为聚集点
            stack.push(current);
          } else {
            // 将之前的聚集点出栈
            let mid = stack[Math.floor(stack.length / 2)];

            result.push({
              ...mid,
              circle: stack.length > 1, //
              s_time: stack[0].s_time,
              e_time: stack[stack.length - 1].e_time,
              repeat_last_time: stack[stack.length - 1].repeat_last_time,
              distance: stack[stack.length - 1].distance,
              clusterSize: stack.length,
              skipService: false
            });
            // update栈
            stack = [{ ...current, circle: false }];
          }
        }
        if (stack.length > 0) {
          // 最后一项出栈
          if (stack.length > 1) {
            // 聚集点
            let mid = stack[Math.floor(stack.length / 2)];
            result.push({
              ...mid,
              circle: true,
              s_time: stack[0].s_time,
              e_time: stack[stack.length - 1].e_time,
              repeat_last_time: stack[stack.length - 1].repeat_last_time,
              distance: stack[stack.length - 1].distance,
              clusterSize: stack.length,
              skipService: false
            });
          } else {
            // length === 0
            result.push({ ...stack[0], circle: false, clusterSize: stack.length, skipService: false });
          }
        }
        return result;
      } catch (e) {
        console.log('decorateListCircle():::', e);
      }
    },
    decorateListAddress(dataList) {
      if (this.$own.isNull(dataList)) {
        return [];
      }
      if (dataList.length === 1) {
        return dataList;
      }
      let result = [];
      let temp = dataList[0] || null;
      for (let i = 1; i < dataList.length; i++) {
        const current = dataList[i];
        if (this.$own.isNotNull(temp) && temp.address === current.address) {
          temp = {
            ...current,
            s_time: temp.s_time
          };
          if (i === dataList.length - 1) {
            result.push(temp);
          }
        } else {
          result.push(temp);
          temp = current;
          if (i === dataList.length - 1) {
            result.push(current);
          }
        }
      }
      return result;
    },
    decorateListSpeed(dataList) {
      if (dataList.length === 1) return [{ ...dataList[0], sp: 0 }];
      let result = [],
        temp = null;
      result = dataList.map((item, i) => {
        if (i === 0) return { ...item, sp: 0 };
        temp = dataList[i - 1];
        const sp = (item.distance / this.calculateTime(temp.e_time, item.s_time)) * this.ms_TO_kmh; // km/h
        return {
          ...item,
          sp
        };
      });
      return result;
    },
    calculateTime(start, end) {
      // 计算两个时间之差（second）
      let s = new Date(start).getTime();
      let e = new Date(end).getTime();
      let dif = Math.abs(e - s) / 1000;
      return dif;
    },
    /**
     * 该函数目的在将路线数组标记上出行方式 walking riding driving transfer
     * 操作即从点到线段的层面
     */
    serviceTypeFilter(data) {
      const result = [];
      // 1、循环经纬度速度数组
      for (let i = 0; i < data.length; i++) {
        if (i === 0) {
          result.push(data[i]);
          continue;
        }

        const preItem = data[i - 1];
        const item = data[i];
        const timeDif = this.calculateTime(preItem.e_time, item.s_time);
        const address = preItem.address;
        if (timeDif >= this.limitSecond) {
          // 当相邻项的时间相隔超过规定时，直连线
          result.push({ ...item, serviceType: this.serviceTypes.overTime });
          continue;
        } else if (this.checkAddress(address, item.address)) {
          // 当相邻项的中文地址相同、包含时，直连线
          result.push({ ...item, serviceType: this.serviceTypes.sameAddress });
          continue;
        } else {
          // 根据速度分类出行方式 type
          result.push({ ...item, serviceType: this.getServiceType(item) });
        }
      } // for() {} done
      return result;
    },
    /**
     * 根据出行方式，而在规定时间区间内，若驾车方式中间夹着其他方式，则将其他方式修正为驾车（方便使用驾车的轨迹纠偏服务）
     * eg. p0-driving p1-walking p2-walking p3-walking p4-driving
     * p0 - p4 时间间隔不超过规定时间 如 15 分钟，则将 p1~p3 的方式改为 driving
     */
    changeToDriving(data) {
      let result = [];
      let nextDrivingIdx = -1;
      for (let i = 0; i < data.length; i++) {
        if (i === 0) {
          result.push(data[i]);
          continue;
        }
        if (data[i].serviceType !== this.serviceTypes.driving && nextDrivingIdx === -1) {
          result.push(data[i]);
        } else if (nextDrivingIdx - i > 0) {
          // 此时出现两个 driving 中间夹着其他方式，将一律改为 driving
          result.push({ ...data[i], serviceType: this.serviceTypes.driving });
        } else if (i < data.length - 2) {
          result.push(data[i]);
          nextDrivingIdx = this.findNextDriving(data, i + 1);
          if (!this.checkTimeDiff(data[i].time, data[nextDrivingIdx].time, this.thresholdTime)) {
            nextDrivingIdx = -1;
          }
        } else {
          result.push(data[i]);
        }
      }
      return result;
    },
    findNextDriving(data, start) {
      let end = 0;
      for (let i = start; i < data.length; i++) {
        if (data[i].serviceType !== this.serviceTypes.driving) {
          continue;
        } else {
          end = i;
          break;
        }
      }
      return end;
    },
    // 单位秒；判断两个时间之差是否在 threshold(阈值) 之内
    checkTimeDiff(start, end, threshold) {
      const startTm = new Date(start).getTime();
      const endTm = new Date(end).getTime();
      return (endTm - startTm) / 1000 <= threshold;
    },
    // 通过速度判断类型
    getServiceType(data) {
      if (data.address.indexOf('高速') >= 0)
        // 包含'高速'使用driving
        return 'driving';
      const sp = data.sp;
      return sp - this.limitSpeed >= 0
        ? 'overSpeed'
        : sp - this.speedTypes.highRailway[0] > 0
        ? 'transfer'
        : sp - this.speedTypes.driving[0] >= 0
        ? 'driving'
        : sp - this.speedTypes.riding[0] > 0
        ? 'riding'
        : 'walking';
    },
    calculateByContext(dataList) {
      let result = [];
      if (this.$own.isNull(dataList)) {
        return [];
      }
      if (dataList.length === 1) {
        return dataList;
      }
      let preWeight = 0;
      const maxWeight = 1;
      for (let i = 0; i < dataList.length; i++) {
        let weight = 0;
        let startP = dataList[i];
        let endP = i === dataList.length - 1 ? null : dataList[i + 1];
        if (endP === null) {
          result.push({ ...dataList[i], weight: preWeight || weight });
          continue;
        }
        const distance = this.calculateDistanceByPoints([startP.lng, startP.lat], [endP.lng, endP.lat]);
        const time = this.calculateTime(startP.e_time, endP.s_time);
        const speed = (distance / time) * this.ms_TO_kmh; // km/h
        if (speed <= this.speedTypes.highRailway[1]) {
          weight++;
        }
        result.push({ ...dataList[i], weight: weight || preWeight });
        preWeight = weight;
      }
      return result.filter(o => o.weight === maxWeight) || [];
    },
    // 通过步行服务获取经纬度
    getPathByWalkingService(data) {
      const routes = data.routes;
      let pathes = [];
      /*routes.forEach(route => {
                    route.steps.forEach(step => {
                        step.path.forEach(path => {
                            pathes.push([ path.lng, path.lat ]);
                        });
                    });
                });*/
      // 默认拿第一个路线
      routes[0].steps.forEach(step => {
        step.path.forEach(path => {
          pathes.push([path.lng, path.lat]);
        });
      });
      return pathes;
    },
    // 通过公交服务获取经纬度
    getPathByTransferService(data) {
      let path = [];
      /*data.plans.forEach(plan => {
                    path = path.concat(plan.path.map(item => {
                        return [ item.lng, item.lat ];
                    }));
                });*/
      // 默认拿第一个路线
      path = path.concat(
        data.plans[0].path.map(item => {
          return [item.lng, item.lat];
        })
      );
      return path;
    },
    // 通过驾车服务获取经纬度
    getPathByDrivingService(data) {
      const routes = data.routes;
      let pathes = [];
      /*routes.forEach(route => {
                    route.steps.forEach(step => {
                        step.path.forEach(path => {
                            pathes.push([ path.lng, path.lat ]);
                        });
                    });
                });*/
      // 默认拿第一个路线
      routes[0].steps.forEach(step => {
        step.path.forEach(path => {
          pathes.push([path.lng, path.lat]);
        });
      });
      return pathes;
    },
    walkingService(location, walkingInstance, callback) {
      return new Promise(res => {
        walkingInstance.search(location[0], location[1], function (status, result) {
          if (status === 'complete') {
            // 使用服务返回的经纬度集合
            res(callback(result, true));
          } else {
            // 使用直连线
            res(callback(result, false));
            console.log('步行路线数据查询失败' + result);
          }
        });
      });
    },
    transferService(location, transferInstance, callback) {
      // 公交地铁
      return new Promise(res => {
        transferInstance.search(location[0], location[1], function (status, result) {
          if (status === 'complete') {
            // 使用服务返回的经纬度集合
            if (result.info && result.info.indexOf(ErrorAMapMsgModel.NO_DATA) >= 0) res(callback(result, false));
            else res(callback(result, true));
          } else {
            // 使用直连线
            res(callback(result, false));
            console.log(`公交路线数据查询失败:::${location}`);
            console.log(result);
          }
        });
      });
    },
    drivingService(location, drivingInstance, callback) {
      // 驾车
      return new Promise(res => {
        drivingInstance.search(location[0], location[1], function (status, result) {
          if (status === 'complete') {
            // 使用服务返回的经纬度集合
            res(callback(result, true));
          } else {
            // 使用直连线
            res(callback(result, false));
            console.log(`驾车路线数据查询失败:::${location}`);
            console.log(result);
          }
        });
      });
    },
    getData_API() {
      ToastService.loading({ message: '数据加载中...', forbidClick: false, getContainer: '#trajectory_map' });
      this.dataList = [];
      this.path = [];
      APIDevice.historyDetailListByIMEI({
        deviceid: this.$store.getters.serialNo,
        mapType: 'gaode',
        start: new Date(this.date).Format('yyyy-MM-dd'),
        end: new Date(this.date).Format('yyyy-MM-dd')
      })
        .then(result => {
          if (result.data.stateCode !== 1) {
            ToastService.clear();
            DialogService.confirm({ title: result.data.message });
          } else {
            // 2022.7. 8 修复 ios端 时间格式 - 不识别的问题，备注: 用正则将接口中时间格式替换成/
            let newData = result.data.data.item[0].map(item => {
              return {
                ...item,
                time: item.time.replace(new RegExp(/(-)/g), '/')
              };
            });
            const filterData = this.deduplicatedANDDecorateList(newData);
            console.log('filterData', filterData);
            const circleData = this.decorateListCircle(filterData);
            console.log('circleData', circleData);
            const speedData = this.decorateListSpeed(circleData);
            console.log('speedData', speedData);
            const filterSpeedData = this.calculateByContext(speedData);
            console.log('filterSpeedData:::', filterSpeedData);
            this.decoratedAddressList = this.decorateListAddress(filterSpeedData);
            this.resetMarker();
            this.clearMap();
            this.setAddressANDTime(filterData[0]);
            // todo 循环经算出各路径的出行方式，将连续 driving 的路径使用轨迹纠偏
            const serviceTypedData = this.serviceTypeFilter(filterSpeedData);
            const drivingFilterData = this.changeToDriving(serviceTypedData);
            console.log('drivingFilterData:::', drivingFilterData);
            this.createServiceV2(drivingFilterData);
          }
        })
        .catch(e => {
          console.log(e);
        })
        .finally(() => () => ToastService.clear());
    },
    async getMap() {
      ToastService.loading({ message: '地图加载中...', forbidClick: false, getContainer: '#trajectory_map' });
      let oldData,
        oldStateCode = 0;
      // 获取头像
      try {
        oldData = await this.getData();
        oldStateCode = oldData.data.stateCode;
        this.imagePath = oldData.data.imagePath;
      } catch (e) {
        ToastService.clear();
      }
      /*const oldData = await this.getData();
                let oldStateCode = 1;
                if (oldData.data.stateCode === 0) {
                    oldStateCode = 0;
                }
                this.imagePath = oldData.data.imagePath;*/

      const plugins = [
        'AMap.Geocoder',
        'AMap.GraspRoad',
        'AMap.GeometryUtil',
        'AMap.CitySearch',
        'AMap.Walking',
        'AMap.Riding',
        'AMap.Transfer',
        'AMap.Driving',
        'AMap.ToolBar'
      ];
      MapLoader(false, plugins).then(
        AMap => {
          // 地图实例
          this.map.instance = new AMap.Map('trajectory_map', {
            center: null,
            resizeEnable: true,
            zoom: this.map.zoom
          });
          if (process.env.NODE_ENV !== 'production') {
            const toolBar = new AMap.ToolBar({ offset: new AMap.Pixel(10, 400), position: 'LT' });
            this.map.instance.addControl(toolBar);
          }

          ToastService.clear();
          if (oldStateCode) {
            this.getData_API();
          }
        },
        e => {
          console.log('加载地图失败，下面是报错数据');
          console.log(e);
        }
      );
    },

    /* todo 轨迹纠偏 start */
    graspRoadService(locationList, drivingInstance, callback) {
      // 轨迹纠偏
      return new Promise(res => {
        drivingInstance.driving(locationList, function (error, result) {
          if (!error) {
            let path2 = [];
            let newPath = result.data.points;
            for (let i = 0; i < newPath.length; i++) {
              const location = [parseFloat(newPath[i].x.toFixed(6)), parseFloat(newPath[i].y.toFixed(6))];
              path2.push(location);
            }
            res(callback(newPath, true));
          } else {
            res(callback(result, false));
            console.log(`轨迹纠偏查询失败:::`, locationList);
            console.log(result);
          }
        });
      });
    },
    /* todo 轨迹纠偏 end */

    async createServiceV2(data) {
      ToastService.loading({ message: '正在加载...' });
      if (data.length === 0) {
        ToastService.clear();
        return;
      }

      let drivingCounts = 0; // 驾车路线的数量
      let wrongItemCounts = 0; // 调用了路线规划后验证此点不符合速度要求的点的数量
      for (let i = 0; i < data.length; i++) {
        if (i === 0) {
          this.path.push([data[i].lng, data[i].lat]);
          continue;
        }
        let preItem = data[i - 1 - wrongItemCounts];
        const item = data[i];
        let location = [
          [preItem.lng, preItem.lat],
          [item.lng, item.lat]
        ];
        let address = preItem.address;
        let timeDif = this.calculateTime(preItem.e_time, item.s_time);

        if (item.serviceType === this.serviceTypes.driving && i !== data.length - 1) {
          // 属于驾车时，累计驾车服务数量
          drivingCounts++;
          continue;
        } else {
          // 当终点服务类型为 非驾车 && drivingCounts > 0 时，调取轨迹纠偏
          // todo 轨迹纠偏
          if (drivingCounts > 0) {
            try {
              const start = i - drivingCounts - 1 - wrongItemCounts,
                end = i - 1;
              const locationList = this.getGraspServiceParamsReady(data, start, end);
              console.log(`共${drivingCounts + 1}项使用了轨迹纠偏:::start_${start}, end_${end}`);
              console.log(`start:::`, data[start]);
              console.log(`end:::`, data[end]);
              console.log(`轨迹纠偏参数:::`, locationList);
              this.serviceLog(preItem.serviceType, data[end]); // 打印 log
              // todo 轨迹纠偏的最后一个参数的 sp 需要归零
              if (locationList.length) {
                locationList[locationList.length - 1].sp = 0;
              }
              await this.graspRoadService(
                locationList,
                // eslint-disable-next-line
                new AMap.GraspRoad(),
                (result, useService) => {
                  if (useService) {
                    this.path = this.path.concat(
                      result.map(item => {
                        return [parseFloat(item.x.toFixed(6)), parseFloat(item.y.toFixed(6))];
                      })
                    );
                    wrongItemCounts = 0;
                  } else {
                    this.addPathByStraight([item.lng, item.lat]);
                    wrongItemCounts = 0;
                  }
                }
              );
            } catch (e) {
              console.log('纠偏报错：：：', e);
            }
            // 由于driving服务改为了轨迹纠偏，是累计方式，那么只有循环到非driving方式才调取轨迹纠偏
            // 所以其他服务需要用到的变量需要重新赋值
            preItem = data[i - 1];
            location = [
              [preItem.lng, preItem.lat],
              [item.lng, item.lat]
            ];
            address = preItem.address;
            timeDif = this.calculateTime(preItem.e_time, item.s_time);
            // 归零
            drivingCounts = 0;
          }

          this.serviceLog(item.serviceType, item); // 打印 log

          // todo 路径规划
          // 调取其他出行方式的路径规划服务
          const isSameAddress = this.checkAddress(address, item.address);
          if (
            item.serviceType === this.serviceTypes.overTime ||
            item.serviceType === this.serviceTypes.overSpeed ||
            isSameAddress ||
            (item.serviceType === this.serviceTypes.sameAddress && wrongItemCounts) ||
            item.serviceType === this.serviceTypes.transfer /* todo 高德暂无高铁服务，改为直连线 */
          ) {
            // 直连线：超时、超速、地址相同/包含
            if (i === 1) {
              this.path = this.path.concat(location);
              this.collectionStraightPoints = this.collectionStraightPoints.concat(location);
              continue;
            }
            let point = [item.lng, item.lat];
            this.path.push(point);
            this.collectionStraightPoints.push(point);
            wrongItemCounts = 0; // 归零
            drivingCounts = 0; // 归零
            continue;
          } else if (item.serviceType === this.serviceTypes.walking || item.serviceType === this.serviceTypes.riding) {
            // 步行、骑行
            await this.walkingService(
              location,
              // eslint-disable-next-line
              new AMap.Walking({ map: this.map.instance, autoFitView: i === data.length - 1, hideMarkers: true }),
              (result, useService) => {
                if (useService) {
                  console.log(`服务返回路程：${result.routes[0].distance} 米`);
                  if (this.checkSpeedByServiceType(result.routes[0].distance / timeDif, item.serviceType)) {
                    this.path = this.path.concat(this.getPathByWalkingService(result));
                    wrongItemCounts = 0;
                  } else if (item.circle) {
                    // 当前点为聚集点
                    this.addPathByStraight([item.lng, item.lat]);
                    wrongItemCounts = 0;
                    console.log('上面的服务不符合，但为聚集点，直连');
                  } else {
                    wrongItemCounts++; // 保留起点
                    item.skipService = true;
                    console.log('上面的服务不符合，跳过');
                  }
                } else {
                  this.addPathByStraight([item.lng, item.lat]);
                  wrongItemCounts = 0;
                  console.log(`步行：：：`, result);
                }
              }
            );
            // eslint-disable-next-line no-dupe-else-if
          } else if (item.serviceType === this.serviceTypes.transfer) {
            // 公交、地铁
            await this.transferService(
              location,
              // eslint-disable-next-line
              new AMap.Transfer({
                map: this.map.instance,
                autoFitView: i === data.length - 1,
                hideMarkers: true,
                city: preItem.cityCode,
                cityd: item.cityCode
              }),
              (result, useService) => {
                if (useService) {
                  console.log(`服务返回路程：${result.plans[0].distance} 米`);
                  if (this.checkSpeedByServiceType(result.plans[0].distance / timeDif, item.serviceType)) {
                    this.path = this.path.concat(this.getPathByTransferService(result));
                    wrongItemCounts = 0;
                  } else if (item.circle) {
                    // 当前点为聚集点
                    this.addPathByStraight([item.lng, item.lat]);
                    wrongItemCounts = 0;
                    console.log('上面的服务不符合，但为聚集点，直连');
                  } else {
                    wrongItemCounts++; // 保留起点
                    item.skipService = true;
                    console.log('上面的服务不符合，跳过');
                  }
                } else {
                  this.addPathByStraight([item.lng, item.lat]);
                  wrongItemCounts = 0;
                  console.log(`公交：：：`, result);
                }
              }
            );
          }
        }
      }
      // for() {} done

      console.log('path::::', this.path);

      ToastService.clear();
      this.clearMap();
      this.polylineList = this.path.map(item => item);
      this.createMarker(this.path);
      this.createPolyline(this.path);
      this.createCircles(data);
    },
    async createServiceV2New(data) {
      // 如果 已经绘制了新的轨迹 则把坐标数组清空 防止第二次以后绘制出现直连线的问题
      if (this.pathNew) {
        this.pathNew = [];
      }
      ToastService.loading({ message: '正在加载...' });
      if (data.length === 0) {
        ToastService.clear();
        return;
      }

      let drivingCounts = 0; // 驾车路线的数量
      let wrongItemCounts = 0; // 调用了路线规划后验证此点不符合速度要求的点的数量
      for (let i = 0; i < data.length; i++) {
        if (i === 0) {
          this.pathNew.push([data[i].lng, data[i].lat]);
          continue;
        }
        let preItem = data[i - 1 - wrongItemCounts];
        const item = data[i];
        let location = [
          [preItem.lng, preItem.lat],
          [item.lng, item.lat]
        ];
        let address = preItem.address;
        let timeDif = this.calculateTime(preItem.e_time, item.s_time);

        if (item.serviceType === this.serviceTypes.driving && i !== data.length - 1) {
          // 属于驾车时，累计驾车服务数量
          drivingCounts++;
          continue;
        } else {
          // 当终点服务类型为 非驾车 && drivingCounts > 0 时，调取轨迹纠偏
          // todo 轨迹纠偏
          if (drivingCounts > 0) {
            try {
              const start = i - drivingCounts - 1 - wrongItemCounts,
                end = i - 1;
              const locationList = this.getGraspServiceParamsReady(data, start, end);
              console.log(`共${drivingCounts + 1}项使用了轨迹纠偏:::start_${start}, end_${end}`);
              console.log(`start:::`, data[start]);
              console.log(`end:::`, data[end]);
              console.log(`轨迹纠偏参数:::`, locationList);
              this.serviceLog(preItem.serviceType, data[end]); // 打印 log
              // todo 轨迹纠偏的最后一个参数的 sp 需要归零
              if (locationList.length) {
                locationList[locationList.length - 1].sp = 0;
              }
              await this.graspRoadService(
                locationList,
                // eslint-disable-next-line
                new AMap.GraspRoad(),
                (result, useService) => {
                  if (useService) {
                    this.pathNew = this.pathNew.concat(
                      result.map(item => {
                        return [parseFloat(item.x.toFixed(6)), parseFloat(item.y.toFixed(6))];
                      })
                    );
                    wrongItemCounts = 0;
                  } else {
                    this.addPathByStraight([item.lng, item.lat]);
                    wrongItemCounts = 0;
                  }
                }
              );
            } catch (e) {
              console.log('纠偏报错：：：', e);
            }
            // 由于driving服务改为了轨迹纠偏，是累计方式，那么只有循环到非driving方式才调取轨迹纠偏
            // 所以其他服务需要用到的变量需要重新赋值
            preItem = data[i - 1];
            location = [
              [preItem.lng, preItem.lat],
              [item.lng, item.lat]
            ];
            address = preItem.address;
            timeDif = this.calculateTime(preItem.e_time, item.s_time);
            // 归零
            drivingCounts = 0;
          }

          this.serviceLog(item.serviceType, item); // 打印 log

          // todo 路径规划
          // 调取其他出行方式的路径规划服务
          const isSameAddress = this.checkAddress(address, item.address);
          if (
            item.serviceType === this.serviceTypes.overTime ||
            item.serviceType === this.serviceTypes.overSpeed ||
            isSameAddress ||
            (item.serviceType === this.serviceTypes.sameAddress && wrongItemCounts) ||
            item.serviceType === this.serviceTypes.transfer /* todo 高德暂无高铁服务，改为直连线 */
          ) {
            // 直连线：超时、超速、地址相同/包含
            if (i === 1) {
              this.pathNew = this.pathNew.concat(location);
              this.collectionStraightPointsNew = this.collectionStraightPointsNew.concat(location);
              continue;
            }
            let point = [item.lng, item.lat];
            this.pathNew.push(point);
            this.collectionStraightPointsNew.push(point);
            wrongItemCounts = 0; // 归零
            drivingCounts = 0; // 归零
            continue;
          } else if (item.serviceType === this.serviceTypes.walking || item.serviceType === this.serviceTypes.riding) {
            // 步行、骑行
            await this.walkingService(
              location,
              // eslint-disable-next-line
              new AMap.Walking({ map: this.map.instance, autoFitView: i === data.length - 1, hideMarkers: true }),
              (result, useService) => {
                if (useService) {
                  console.log(`服务返回路程：${result.routes[0].distance} 米`);
                  if (this.checkSpeedByServiceType(result.routes[0].distance / timeDif, item.serviceType)) {
                    this.pathNew = this.pathNew.concat(this.getPathByWalkingService(result));
                    wrongItemCounts = 0;
                  } else if (item.circle) {
                    // 当前点为聚集点
                    this.addPathByStraight([item.lng, item.lat]);
                    wrongItemCounts = 0;
                    console.log('上面的服务不符合，但为聚集点，直连');
                  } else {
                    wrongItemCounts++; // 保留起点
                    item.skipService = true;
                    console.log('上面的服务不符合，跳过');
                  }
                } else {
                  this.addPathByStraight([item.lng, item.lat]);
                  wrongItemCounts = 0;
                  console.log(`步行：：：`, result);
                }
              }
            );
            // eslint-disable-next-line no-dupe-else-if
          } else if (item.serviceType === this.serviceTypes.transfer) {
            // 公交、地铁
            await this.transferService(
              location,
              // eslint-disable-next-line
              new AMap.Transfer({
                map: this.map.instance,
                autoFitView: i === data.length - 1,
                hideMarkers: true,
                city: preItem.cityCode,
                cityd: item.cityCode
              }),
              (result, useService) => {
                if (useService) {
                  console.log(`服务返回路程：${result.plans[0].distance} 米`);
                  if (this.checkSpeedByServiceType(result.plans[0].distance / timeDif, item.serviceType)) {
                    this.pathNew = this.pathNew.concat(this.getPathByTransferService(result));
                    wrongItemCounts = 0;
                  } else if (item.circle) {
                    // 当前点为聚集点
                    this.addPathByStraight([item.lng, item.lat]);
                    wrongItemCounts = 0;
                    console.log('上面的服务不符合，但为聚集点，直连');
                  } else {
                    wrongItemCounts++; // 保留起点
                    item.skipService = true;
                    console.log('上面的服务不符合，跳过');
                  }
                } else {
                  this.addPathByStraight([item.lng, item.lat]);
                  wrongItemCounts = 0;
                  console.log(`公交：：：`, result);
                }
              }
            );
          }
        }
      }
      // for() {} done
      ToastService.clear();
      this.resetMarkerNew();
      this.polylineList = this.pathNew.map(item => item);
      this.createMarkerNew(this.pathNew);
      this.createPolylineNew(this.pathNew);
      this.createCirclesNew(data);
    },
    // 组装轨迹纠偏参数
    getGraspServiceParamsReady(data, start, end) {
      const tm0 = Math.round(new Date(data[start].s_time).getTime() / 1000);
      return data.slice(start, end + 1).map((item, i) => {
        const tmI = Math.round(new Date(item.e_time).getTime() / 1000) - tm0;
        return {
          x: item.lng,
          y: item.lat,
          sp: item.sp,
          ag: 0,
          tm: i === 0 ? tm0 : tmI
        };
      });
    },
    serviceLog(type, item) {
      console.log(`服务::::${type}`);
      console.log('终点::::', item);
      console.count('------------------');
    },
    // 验证路径规划服务的结果是否符合情景
    // 根据服务结果计算出的速度是否符合设定的区间
    checkSpeedByServiceType(sp, type) {
      sp = sp * this.ms_TO_kmh; // m/s 转 km/h
      let result = true;
      switch (type) {
        case 'walking':
        case 'riding':
          result = sp <= this.speedTypes.riding[1];
          break;
        case 'driving':
          result = sp <= this.speedTypes.driving[1] && sp > this.speedTypes.driving[0];
          break;
        case 'transfer':
          result = sp <= this.speedTypes.highRailway[1] && sp >= this.speedTypes.highRailway[0];
          break;
      }
      if (!result) console.log(`服务返回速度结果不符合预设区间，服务类型：${type}，速度：${sp} km/h`);
      return result;
    },
    // 检查中文地址是否相同、包含
    checkAddress(addA, addB) {
      return addA === addB || addA.indexOf(addB) >= 0 || addB.indexOf(addA) >= 0;
    },
    addPathByStraight(destinationLngLat) {
      this.path.push(destinationLngLat);
      this.collectionStraightPoints.push(destinationLngLat);
    },
    // 清除地图的覆盖物
    clearMap() {
      this.map.instance.clearMap();
    },
    resetMarker() {
      this.map.marker = {};
      this.map.polyline = {};
      this.map.passedPolyline = {};
    },
    resetMarkerNew() {
      this.map.marker = {};
      this.map.polylineNew = {};
      this.map.passedPolylineNew = {};
    },
    assemblePolylineList(lngLatList) {
      this.polylineList = lngLatList.map(item => item);
    },
    createCircles(dataList) {
      dataList.forEach((item, i) => {
        if (i === dataList.length - 1) {
          let center = [item.lng, item.lat];
          // eslint-disable-next-line
          let circle = new AMap.Circle({
            center,
            radius: this.limitDistance, // 半径
            borderWeight: 3,
            strokeColor: '#2599ff',
            strokeWeight: 4,
            strokeOpacity: 0.4,
            fillOpacity: 0.2,
            fillColor: '#2599ff',
            zIndex: 10
          });
          circle.setMap(this.map.instance);
          this.circleList.push(circle);
          return;
        }
        if (item.circle /* && !item.skipService*/) {
          let center = [item.lng, item.lat];
          // eslint-disable-next-line
          let circle = new AMap.Circle({
            center,
            radius: this.limitDistance, // 半径
            borderWeight: 3,
            strokeColor: '#fa796e',
            strokeWeight: 4,
            strokeOpacity: 0.4,
            fillOpacity: 0.2,
            //                        fillColor: "#2599ff",
            fillColor: '#fa796e',
            zIndex: 10
          });
          circle.setMap(this.map.instance);
          this.circleList.push(circle);
        }
      });
    },
    createCirclesNew(dataList) {
      dataList.forEach((item, i) => {
        if (i === dataList.length - 1) {
          let center = [item.lng, item.lat];
          // eslint-disable-next-line
          let circle = new AMap.Circle({
            center,
            radius: this.limitDistance, // 半径
            borderWeight: 3,
            strokeColor: '#2599ff',
            strokeWeight: 4,
            strokeOpacity: 0.4,
            fillOpacity: 0.2,
            fillColor: '#2599ff',
            zIndex: 10
          });
          circle.setMap(this.map.instance);
          this.circleListNew.push(circle);
          return;
        }
        if (item.circle /* && !item.skipService*/) {
          let center = [item.lng, item.lat];
          // eslint-disable-next-line
          let circle = new AMap.Circle({
            center,
            radius: this.limitDistance, // 半径
            borderWeight: 3,
            strokeColor: '#fa796e',
            strokeWeight: 4,
            strokeOpacity: 0.4,
            fillOpacity: 0.2,
            //                        fillColor: "#2599ff",
            fillColor: '#fa796e',
            zIndex: 10
          });
          circle.setMap(this.map.instance);
          this.circleListNew.push(circle);
        }
      });
    },
    createMarker(dataList) {
      let center;
      if (dataList[0].lng && dataList[0].lat) {
        center = [dataList[0].lng, dataList[0].lat];
      } else {
        center = [dataList[0][0], dataList[0][1]];
      }
      let content = `<div class="imageArea">
                                <img class="image_area" src="${this.imagePath}" />
                                <em></em>
                             </div>`;
      /*let content = `<div class="img">
                                   <div class="image_area">
                                       <img src="${this.imagePath}" />
                                       <i></i>
                                   </div>
                                   <div class="circel"></div>
                               </div>`;*/
      // eslint-disable-next-line no-undef
      this.map.marker = new AMap.Marker({ position: center, content, offset: new AMap.Pixel(-29, -76) });
      this.map.instance.add(this.map.marker);
      this.map.instance.setCenter(center);
    },
    createMarkerNew(dataList) {
      let center;
      if (dataList[0].lng && dataList[0].lat) {
        center = [dataList[0].lng, dataList[0].lat];
      } else {
        center = [dataList[0][0], dataList[0][1]];
      }
      let content = `<div class="imageArea">
                                <img class="image_area" src="${this.imagePath}" />
                                <em></em>
                             </div>`;
      /*let content = `<div class="img">
                                   <div class="image_area">
                                       <img src="${this.imagePath}" />
                                       <i></i>
                                   </div>
                                   <div class="circel"></div>
                               </div>`;*/
      // eslint-disable-next-line no-undef
      this.map.marker = new AMap.Marker({ position: center, content, offset: new AMap.Pixel(-58, -152) });
      this.map.instance.add(this.map.marker);
      this.map.instance.setCenter(center);
    },
    createPolyline(lngLatList) {
      const data = lngLatList.map(item => item);
      // eslint-disable-next-line
      this.map.polyline = new AMap.Polyline({
        map: this.map.instance,
        path: data,
        strokeColor: '#43598a', //线颜色
        strokeOpacity: 0.8, //线透明度
        strokeWeight: 12, //线宽
        //                    strokeStyle: "solid", //线样式
        lineJoin: 'round',
        lineCap: 'round',
        showDir: true,
        geodesic: true
      });
      // eslint-disable-next-line
      this.map.passedPolyline = new AMap.Polyline({
        map: this.map.instance,
        strokeColor: '#ffc554', //线颜色
        strokeOpacity: 0.9, //线透明度
        strokeWeight: 10, //线宽
        lineJoin: 'round',
        lineCap: 'round',
        showDir: true,
        geodesic: true
      });

      let start_idx = 0;
      this.map.marker.on('moving', e => {
        try {
          this.map.passedPolyline.setPath(e.passedPath);
          this.lngLatOnMoving = e.passedPath.map(o => {
            return [o.lng, o.lat];
          });
          if (start_idx >= this.dataList.length) return;
          const length = this.lngLatOnMoving.length;
          const radius = 40; // 距离条件
          const idx = start_idx - 1 < 0 ? start_idx : start_idx - 1;
          const circleCenterLngLat = [this.dataList[idx].lng, this.dataList[idx].lat];
          const isLess = this.checkDistanceLessThanRadius(circleCenterLngLat, this.lngLatOnMoving[length - 1], radius);
          if (!isLess) {
            this.setAddressANDTime(this.dataList[idx]);
          } else {
            start_idx++;
            this.setAddressANDTime(this.dataList[start_idx]);
          }
        } catch (e) {
          console.log('fail：：moving::::', e);
        }
      });
    },
    // 绘制 一条对比的轨迹
    createPolylineNew(lngLatList) {
      console.log('lngLatList', lngLatList);
      const data = lngLatList.map(item => item);
      console.log('data', data);
      // eslint-disable-next-line
      this.map.polylineNew = new AMap.Polyline({
        map: this.map.instance,
        path: data,
        strokeColor: 'red', //线颜色
        strokeOpacity: 0.8, //线透明度
        strokeWeight: 12, //线宽
        //                    strokeStyle: "solid", //线样式
        lineJoin: 'round',
        lineCap: 'round',
        showDir: true,
        geodesic: true
      });
      // eslint-disable-next-line
      this.map.passedPolylineNew = new AMap.Polyline({
        map: this.map.instance,
        strokeColor: '#ffc554', //线颜色
        strokeOpacity: 0.9, //线透明度
        strokeWeight: 10, //线宽
        lineJoin: 'round',
        lineCap: 'round',
        showDir: true,
        geodesic: true
      });

      let start_idx = 0;
      this.map.marker.on('moving', e => {
        try {
          this.map.passedPolylineNew.setPath(e.passedPath);
          this.lngLatOnMovingNew = e.passedPath.map(o => {
            return [o.lng, o.lat];
          });
          if (start_idx >= this.dataListNew.length) return;
          const length = this.lngLatOnMovingNew.length;
          const radius = 40; // 距离条件
          const idx = start_idx - 1 < 0 ? start_idx : start_idx - 1;
          const circleCenterLngLat = [this.dataListNew[idx].lng, this.dataListNew[idx].lat];
          const isLess = this.checkDistanceLessThanRadius(
            circleCenterLngLat,
            this.lngLatOnMovingNew[length - 1],
            radius
          );
          if (!isLess) {
            this.setAddressANDTime(this.dataListNew[idx]);
          } else {
            start_idx++;
            this.setAddressANDTime(this.dataListNew[start_idx]);
          }
        } catch (e) {
          console.log('fail：：moving::::', e);
        }
      });
    },
    // 比较两点的距离是否小于半径
    checkDistanceLessThanRadius(circleCenterLngLat, targetLngLat, radius) {
      // eslint-disable-next-line no-undef
      const distance = parseInt(AMap.GeometryUtil.distance(circleCenterLngLat, targetLngLat));
      return radius - distance > 0;
    },
    setAddressANDTime(o) {
      if (this.$own.isNotNull(o)) {
        this.address = o.address;
        this.time = o.time;
      }
    },
    toggleBottom(bool) {
      this.bottomContentShow = bool;
    },

    // 旧版本 start
    getData() {
      return new Promise((resolve, reject) => {
        /* let url = `/api/Location/History`;
                    let jsonData = {
                        deviceId: this.$store.getters.deviceId,
                        dateTime: new Date(this.date),
                        mapType: "gaode",
                        timeOffset: -new Date().getTimezoneOffset() / 60
                    }; */
        /* this.$axios
                        .post(url, jsonData) */
        APIDevice.history({
          deviceId: this.$store.getters.deviceId,
          dateTime: new Date(this.date),
          mapType: 'gaode',
          timeOffset: -new Date().getTimezoneOffset() / 60
        })
          .then(res => {
            resolve(res);
            if (res.data.stateCode === 0 && res.data.list == null) {
              DialogService.confirm({ title: res.data.message /* className: 'device_confirm'  */ });
              ToastService.clear();
            }
          })
          .catch(err => {
            reject(err);
            //                            Dialog({ title: '您的网络异常', message: '请稍后重试', className: 'device_confirm' });
          })
          .finally(() => (this.showOverlay = false));
      });
    },
    // 旧版本 end

    //逆地理编码
    geocoder(value, type) {
      //value是坐标（数组） type传入的boolean
      let that = this;

      new Promise((resolve, reject) => {
        let MGeocoder = null;
        let obj = {};
        that.map.plugin(['AMap.Geocoder'], () => {
          // eslint-disable-next-line no-undef
          MGeocoder = new AMap.Geocoder({
            radius: 1000,
            extensions: 'all'
          });

          MGeocoder.getAddress(value, (status, result) => {
            if (status == 'complete' && result.info == 'OK') {
              let address = result.regeocode.formattedAddress;
              obj = { address };
              resolve(obj);
            } else {
              reject(obj);
            }
          });
        });
      })
        .then(res => {
          if (type) return true;
          that.bottomContentShow = true;
          that.address = res.address;
        })
        .catch(err => {
          //                        that.bottomContentShow = false;
          that.address = '无效的地理位置';
          console.log(err);
          if (type) {
            return false;
          } else {
            console.log('坐标参数错误');
            // that.dialog("坐标参数错误");
          }
        });
    },
    playerControl() {
      this.playFlag = !this.playFlag;
      if (this.playFlag) {
        this.num = 0;
        this.marker.moveAlong(this.lineArr, this.leftCode);
        console.log('开始了！');
      } else {
        this.marker.pauseMove();
        console.log('暂停了！再次点击将重来');
      }
    },
    dateClick(type) {
      this.playFlag = false;
      this.calendarShow = false;
      this.initTime();
      if (type == 'add' && this.clickFlag) {
        if (this.count >= 0) {
          return;
        }
        this.count++;
        this.date = this.$own.getNowFormatDate(this.count);
        this.handleMinDate(this.date);
        this.defaultDate = new Date(this.date.replace(/-/g, '/'));
        //                    this.getData();
        //                    this.getAmap();
        this.getData_API();
      } else {
        if (this.clickFlag) {
          this.count--;
          this.date = this.$own.getNowFormatDate(this.count);
          this.handleMinDate(this.date);
          this.defaultDate = new Date(this.date.replace(/-/g, '/'));
          //                        this.getData();
          //                        this.getAmap();
          this.getData_API();
        }
      }
    },
    handleMinDate() {
      /* let getYear = new Date(date).getFullYear();
                let getMonth = new Date(date).getMonth(); */
      // TODO #BUG 取消点击选择日期时最小日期自动变化
      /* this.minDate = new Date(getYear, getMonth, 1); */
    },
    dateAreaClick() {
      this.calendarShow = !this.calendarShow;
    },
    onSelect(val) {
      this.date = new Date(val).Format('yyyy-MM-dd');
      this.handleMinDate(val);
      let nowTime = new Date(new Date().Format('yyyy-MM-dd')).getTime();
      let newTime = new Date(this.date).getTime();
      this.count = (newTime - nowTime) / (60 * 60 * 24 * 1000);
      this.calendarShow = false;
      this.initTime();
      this.closeTimePicker();
      //                this.getData();
      //                this.getAmap();
      this.getData_API();
    },
    // 根据时间端选择轨迹
    historyDetailListByIMEI() {
      ToastService.loading({
        message: '数据加载中...',
        forbidClick: false,
        getContainer: '#trajectory_map'
      });
      this.dataList = [];
      this.path = [];
      let date = new Date(this.date).Format('yyyy-MM-dd');
      let startTime = date + ' ' + this.initTimePick.initStartTime;
      let endTime = date + ' ' + this.initTimePick.initEndTime;
      APIDevice.historyDetailListByIMEI({
        deviceid: this.$store.getters.serialNo,
        mapType: 'gaode',
        start: startTime,
        end: endTime
      })
        .then(result => {
          if (result.data.stateCode !== 1) {
            ToastService.clear();
            DialogService.confirm({ title: result.data.message });
          } else {
            const filterData = this.deduplicatedANDDecorateList(result.data.data.item[0]);
            console.log('filterData', filterData);
            const circleData = this.decorateListCircle(filterData);
            console.log('circleData', circleData);
            const speedData = this.decorateListSpeed(circleData);
            console.log('speedData', speedData);
            const filterSpeedData = this.calculateByContext(speedData);
            console.log('filterSpeedData:::', filterSpeedData);
            this.decoratedAddressList = this.decorateListAddress(filterSpeedData);
            this.resetMarker();
            this.clearMap();
            this.setAddressANDTime(filterData[0]);
            // todo 循环经算出各路径的出行方式，将连续 driving 的路径使用轨迹纠偏
            const serviceTypedData = this.serviceTypeFilter(filterSpeedData);
            const drivingFilterData = this.changeToDriving(serviceTypedData);
            console.log('drivingFilterData:::', drivingFilterData);
            this.createServiceV2(drivingFilterData);
          }
        })
        .catch(e => {
          console.log('错误::', e);
          ToastService.clear();
        })
        .finally(() => {
          ToastService.clear();
        });
    },
    // 点击'时间'快捷方式
    onTimeClick() {
      console.log('点击了时间');
      this.timePickWidth = 80;
      this.timeWidth = 20;
      this.isLeft = false;
      this.isPopup = !this.isPopup;
      if (!this.isPopup) {
        this.timePickWidth = 20;
        this.timeWidth = 100;
        this.isLeft = true;
      }
    },
    // 点击开始时间
    onStartClick() {
      this.timePickData.timePickStartShow = !this.timePickData.timePickStartShow;
      this.timePickData.timePickEndShow = false;
      this.calendarShow = false;
    },
    // 点击结束时间
    onEndClick() {
      this.timePickData.timePickEndShow = !this.timePickData.timePickEndShow;
      this.timePickData.timePickStartShow = false;
      this.calendarShow = false;
    },
    // 点击确认开始时间
    onStartTimeConfirm(startTime) {
      this.initTimePick.initStartTime = startTime;
      console.log('startTime', startTime);
      this.onCloseTimePicker();
    },
    // 点击取消开始时间
    onStartTimeCancel() {
      this.timePickData.timePickStartShow = false;
    },
    // 点击确认结束时间
    onEndTimeConfirm(endTime) {
      this.initTimePick.initEndTime = endTime;
      console.log('结束时间', endTime);
      this.timePickData.timePickEndShow = false;
    },
    // 点击取消结束时间
    onEndTimeCancel() {
      this.timePickData.timePickEndShow = false;
    },
    // 关闭开始时间选择器,开始结束时间选择器
    onCloseTimePicker() {
      this.timePickData.timePickStartShow = false;
      this.timePickData.timePickEndShow = true;
    },
    // 查看轨迹
    onConfirm() {
      this.closeTimePicker();
      this.historyDetailListByIMEI();
    },
    // // 关闭时间选择器
    closeTimePicker() {
      this.timePickWidth = 20;
      this.timeWidth = 80;
      this.isLeft = false;
      this.isPopup = false;
    },
    // 初始化时间选择器的时间
    initTime() {
      this.initTimePick.initStartTime = '00:00';
      this.initTimePick.initEndTime = '23:59';
      this.timePickData.selectStartTime = '00:00'; //初始化选择器内的时间
      this.timePickData.selecttEndTime = '23:59';
    },
    // 判断字符串是否可以转化为json数据
    isJsonString(str) {
      try {
        if (typeof JSON.parse(str) == 'object') {
          return true;
        }
      } catch (e) {
        /* empty */
      }
      return false;
    },
    onDialogCancel() {
      this.dialogInput = '';
    }
  }
};
</script>

<style lang="scss">
@import './trajectory.scss';
.player {
  i {
    color: #fff;
  }
}

.img {
  position: relative;
  height: 84px;
  display: flex;
  flex-flow: column;
  justify-content: flex-start;
  align-items: center;
  border-radius: 50%;
  z-index: 3;
}

.img .circel {
  position: absolute;
  bottom: 0;
  width: 90px;
  height: 90px;
  /*background: rgba(255, 150, 37, 0.2);*/
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.img .circel:before {
  content: '';
  position: absolute;
  width: 30px;
  height: 30px;
  background: #fff;
  border-radius: 50%;
  z-index: 3;
}

.img .circel:after {
  content: ' ';
  position: absolute;
  width: 24px;
  height: 24px;
  background: #ff9625;
  border-radius: 50%;
  z-index: 4;
}

.img .image_area {
  position: relative;
  width: 92px;
  height: 92px;
  border-radius: 50%;
  background: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 4;
}

.img .image_area:after {
  content: '';
  position: absolute;
  bottom: -10px;
  width: 0;
  height: 0;
  border-top: 12px solid #fff;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
}

.img .image_area img {
  width: 84px;
  height: 84px;
  border-radius: 50%;
  object-fit: cover;
}

.img.online .image_area:after {
  border-top-color: #5fcc0e;
}

.img.online .image_area {
  background: #5fcc0e;
}

.img.unline .image_area:after {
  border-top-color: #b5b5b5;
}

.img.unline .image_area {
  background: #b5b5b5;
}

.imageArea {
  position: relative;
  display: flex;
  flex-flow: column;
  justify-content: center;
  align-items: center;
  width: 60px;
  height: 80px;
  background: url(../../assets/img/tooltip-sizing.png);
}

.imageArea img {
  position: absolute;
  top: 17px;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  background: rgb(197, 94, 47);
  object-fit: cover;
}

.imageArea em {
  position: absolute;
  top: 128px;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 30px;
  height: 30px;
  background: #fff;
  border-radius: 50%;
}

.imageArea em:after {
  content: ' ';
  width: 24px;
  height: 24px;
  background: #ff9625;
  border-radius: 50%;
}

.circleArea {
  width: 80px;
  height: 80px;
  background: rgba(37, 153, 255, 0.3);
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.circleArea i {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 30px;
  height: 30px;
  background: #fff;
  border-radius: 50%;
}

.circleArea i:after {
  content: ' ';
  width: 24px;
  height: 24px;
  background: #2599ff;
  border-radius: 50%;
}

.c {
  width: 14px;
  height: 14px;
  border: 3px solid #3296fa;
  border-radius: 50%;
  background: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
}

.c:before {
  content: '';
  width: 10px;
  height: 10px;
  background: #3296fa;
  border-radius: 50%;
}

.end {
  width: 50px;
  height: 50px;
  background-color: #ff0;
  background: transparent url(../../assets/icon.png) no-repeat;
  background-size: 400px 400px;
  background-position: -250px -150px;
}

.trajectory {
  height: 100vh;
  position: relative;
  overflow: hidden;
  .trajectory-con {
    position: relative;
    /*  height: calc(100vh - 100px); */
    overflow: scroll;
    .top {
      width: 100%;
      position: absolute;
      left: 0;
      top: 0;
      z-index: 999;
      background: #fff;

      .dateArea {
        padding: 0 30px;
        height: 100px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        z-index: 999;
        i {
          @include center();
          width: 62px;
          height: 62px;
          border-radius: 50%;
          background: rgba(207, 207, 207, 0.36);

          &:before {
            content: '';
            width: 50px;
            height: 50px;
            @include icon();
            @include icon_position(50, 50, 100, 0);
          }

          &.right {
            &:before {
              @include icon_position(50, 50, 100, 50);
            }

            &.active {
              background: #c8e5ff;

              &:before {
                transform: rotate(180deg);
                @include icon_position(50, 50, 100, 0);
              }
            }
          }

          &.active {
            background: #c8e5ff;
          }
        }

        span {
          @include colorAndFont(#2599ff, 36);
          @include center();

          &:after {
            content: '';
            margin: 6px 0 0 8px;
            width: 0;
            height: 0;
            border-top: 12px solid $blue;
            border-left: 13px solid transparent;
            border-right: 13px solid transparent;
            border-radius: 10px;
          }
        }
      }
    }
    // 时间段选择项
    .time-picker {
      position: absolute;
      right: -20px;
      top: 250px;
      height: 80px;
      display: flex;
      justify-content: flex-start;
      background-color: #ffff;
      border-radius: 10px;
      box-shadow: 0 0 10px rgba(185, 185, 185, 0.9);
      z-index: 99;
      .time-picker-left {
        height: 80px;
        width: 30%;
        line-height: 60px;
        .van-icon-arrow-left,
        .van-icon-arrow {
          height: 10px;
          width: 20px;
          line-height: 40px;
          font-size: 14px;
        }
        span {
          font-size: 32px;
        }
      }
      .time-picker-right {
        height: 80px;
        width: 50%;
        line-height: 70px;
        text-align: center;
        span,
        label {
          font-size: 32px;
        }
        span {
          color: #2599ff;
        }
        label {
          padding: 10px;
        }
      }
      .datetimePicker {
        position: relative;
        top: 8px;
        right: 120px;
        width: 580px;
      }
      .time-picker-right-confirm {
        height: 80px;
        width: auto;
        display: flex;
        justify-content: center;
        align-items: center;
        line-height: 80px;
        text-align: center;
        padding-right: 20px;
        color: white;

        .right-confirm-text {
          height: 60px;
          width: 120px;
          line-height: 50px;
          background-color: #2599ff;
          border-radius: 10px;
          span {
            font-size: 32px;
          }
        }
      }
    }
    // 添加轨迹对比
    .bottom {
      width: 100%;
      position: fixed;
      left: 0;
      bottom: 0;
      z-index: 600;
      box-shadow: 0 0 20px rgba(185, 185, 185, 0.4);

      .conArea {
        position: relative;
      }

      .con {
        padding: 20px;
        background: #fff;
        border-radius: 24px 24px 0 0;
        .content-list {
          min-height: 100px;
          max-height: 200px;
          overflow: scroll;
          padding: 30px 0 0 30px;
          .content-item {
            margin-bottom: 10px;
          }
        }

        .title {
          width: 580px;
          @include colorAndFont(#333, 34);
          /*margin-bottom: px2rem(36);*/
        }

        .adr {
          @include colorAndFont(#999, 28);
          margin-bottom: px2rem(18);

          span {
            margin-left: 15px;
            padding: 0 8px;
            height: 30px;
            @include colorAndFont(#999, 20);
            background: #fafafa;
            border: 1px solid #b5b5b5;
            border-radius: 4px;
          }
        }

        .states {
          display: flex;
          justify-content: flex-start;
          align-items: center;
          span {
            display: flex;
            justify-content: flex-start;
            align-items: center;
            @include colorAndFont(#999, 24);
          }
        }
      }

      .player {
        position: absolute;
        right: 40px;
        top: 50%;
        margin-top: -42px;
        width: 84px;
        height: 84px;
        background: $blue;
        border-radius: 50%;
        box-shadow: 0 0 30px rgba(37, 153, 255, 0.4);
        @include center();

        i.play-icon {
          position: relative;
          width: 50px;
          height: 50px;
          @include center;
          @include icon();
          @include icon_position(50, 50, 100, 100);
          &.stop {
            background: unset;
            &:before,
            &:after {
              content: '';
              width: 8px;
              height: 32px;
              background-color: #fff;
              border-radius: 4px;
            }
            &:before {
              margin-right: 14px;
            }
          }
        }
      }
    }

    .slider-bar {
      position: absolute;
      right: 30px;
      top: -450px;
      padding: 60px 10px;
      width: 60px;
      height: 300px;
      background-color: #fff;
      border-radius: 10px;
      @include center();
      flex-flow: column;
      @include colorAndFont(#666, 16);

      .bar {
        height: 100%;
        margin: 20px 0;
      }
      .van-slider__button {
        width: 30px;
        height: 30px;
      }
      span {
        font-size: 20px;
      }
    }
  }
}
</style>
