<template>
  <div class="airway-edit dialog1027" v-interact>
    <div class="dialog-header">
      <img class="dialog-header__icon" src="../../../../../../assets/images/mount_head.png" />
      <div class="dialog-header__title">手动规划</div>
      <div class="dialog-header__close" @click="$emit('close')">关闭</div>
    </div>
    <div class="dialog-content">
      <div class="ae-page">
        <div v-hover @click="onPrev">上一航点</div>
        <div>{{ pageIndex }} / {{ pageCount }}</div>
        <div v-hover @click="onNext">下一航点</div>
      </div>
      <el-form class="ae-form" :form="curForm" label-width="100px">
        <el-form-item label="航线名称" required>
          <el-input clearable v-model="name"></el-input>
        </el-form-item>
        <el-form-item label="所属单位：" required>
          <el-cascader ref="CascaderRef" v-model="departmentId" :options="orgList" clearable :show-all-levels="false"
            placeholder="请选择所属单位" :props="{
              children: 'children',
              label: 'name',
              value: 'id',
              checkStrictly: true,
              emitPath: false,
            }" @change="changeNode"></el-cascader>
        </el-form-item>
        <el-form-item label="航线速度" prop="speed">
          <el-input clearable v-model="curForm.speed"></el-input>
        </el-form-item>
        <el-form-item label="目标位置" prop="address">
          <el-autocomplete :popper-append-to-body="false" v-model="curForm.address" :fetch-suggestions="onAddressInput"
            placeholder="请输入目标位置" :trigger-on-focus="false" @select="(item) => {
              onAddressChange(item, 'end');
            }
              " clearable>
            <template slot-scope="{ item }">
              <div>
                <span style="font-size: 14px; color: #9e9e9e">
                  {{
                    item.name
                  }}
                </span>
                <span style="font-size: 12px; color: #999; margin-left: 12px">{{ item.address }}</span>
              </div>
            </template>
            <el-button slot="append" icon="el-icon-location" @click="onPickAddress"></el-button>
          </el-autocomplete>
        </el-form-item>
        <el-form-item label="纬度" prop="latitude">
          <el-input clearable v-model="curForm.latitude"></el-input>
        </el-form-item>
        <el-form-item label="经度" prop="longitude">
          <el-input clearable v-model="curForm.longitude"></el-input>
        </el-form-item>
        <el-form-item label="高度" prop="altitude">
          <el-input clearable v-model="curForm.altitude"></el-input>
        </el-form-item>
        <el-form-item label="航线标签" prop="label">
          <el-input clearable v-model="curForm.label"></el-input>
        </el-form-item>
        <el-form-item label="航点动作">
          <el-button type="text" @click="showActions = true">{{ curForm.actions.length }}个动作</el-button>
        </el-form-item>
        <el-form-item label="航线总里程">{{ distance }}m</el-form-item>
        <el-form-item label="预计飞行时间">{{ time }}</el-form-item>
      </el-form>
      <div class="ae-btns">
        <el-button type="primary" @click="onSave" :loading="saveLoading">保存</el-button>
        <el-button type="danger" @click="onDel">删除航点</el-button>
      </div>
    </div>
    <Actions v-if="showActions" @close="showActions = false" @save="onActionsSave" :selectActions="curForm.actions">
    </Actions>
  </div>
</template>

<script>
import { Map, AirLine, TaskInfo } from "../../../../../../../../../../../../api";
import { mapState } from "vuex";
import Utils from "../../../../../../../../../../../../components/cesiumLayer/lib/cesium/utils";
import { nanoid } from "nanoid";
import Actions from "./components/actions";

/**
 * 秒转时分秒
 */
function convertSecondsToHMS(seconds) {
  var hours = Math.floor(seconds / 3600);
  var minutes = Math.floor((seconds % 3600) / 60);
  var remainingSeconds = seconds % 60;

  return hours + "小时 " + minutes + "分钟 " + remainingSeconds + "秒";
}

class Airway {
  uuid = nanoid();
  speed = "6";
  address = "";
  latitude = "";
  longitude = "";
  altitude = "100";
  label = "";
  actions = [];
  position = null; // cesium卡迪尔积三维数据
  distance = 0; // 与上一个航点的距离
}
export default {
  name: "AirwayEdit",
  components: {
    Actions,
  },
  inject: ["rootNode"],
  data() {
    return {
      orgList: [],
      name: "", //航线名
      departmentId: "", //部门id
      form: [], //表单集合
      pageIndex: 0, //当前页码
      locationIcon: null, //定位图标
      handler: null, //地图内容抓取事件
      dataSource: null, //航点数据集
      positions: [], //航点坐标集合
      isPickAddress: false, //是否通过目标位置对地理信息
      showActions: false, // 打开航点动作
      saveLoading: false,
    };
  },
  computed: {
    ...mapState("MMCFlightControlCenter", ["cesiumViewer", "userInfo"]),
    ...mapState("MMCFlightControlCenter/hangar", ["hangar"]),
    // 当前的表单
    curForm() {
      return this.form[this.pageIndex - 1] || new Airway();
    },
    //总页数,
    pageCount() {
      return this.form.length;
    },
    //总里程
    distance() {
      let distance = 0;
      this.form.forEach((item) => {
        distance += item.distance;
      });
      return distance;
    },
    //预计总时间
    time() {
      let time = 0;
      this.form.forEach((item) => {
        let speed = item.speed || 1;
        time += parseInt(item.distance / speed);
      });
      return convertSecondsToHMS(time);
    },
  },
  mounted() {
    let viewer = this.cesiumViewer;
    this.getOrgList()
    this.dataSource = new Cesium.CustomDataSource("airway_edit");
    viewer.dataSources.add(this.dataSource);
    this.handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas); //获取事件对象
    // 绘制航线
    let polyline = this.dataSource.entities.add({
      polyline: {
        material: Cesium.Color.RED,
        width: 3,
        positions: new Cesium.CallbackProperty(() => {
          return this.positions.map((item) => {
            let wgs84 = Utils.transformCartesian2WGS84(item);
            return Utils.transformWGS842Cartesian({
              lng: wgs84.lng,
              lat: wgs84.lat,
              alt: wgs84.alt + 10,
            });
          });
        }, false),
      },
    });
    // 监听取点事件
    this.handler.setInputAction(
      this.onPickPoint,
      Cesium.ScreenSpaceEventType.LEFT_CLICK
    );
    this.pickerPointInit();

  },
  beforeDestroy() {
    this.handler.removeInputAction(
      this.onPickPoint,
      Cesium.ScreenSpaceEventType.LEFT_DOWN
    );
    // todo 连续两次创建航线后销毁cesium会崩溃, 原因未知, 改为隐藏
    /* this.$nextTick(() => {
      let list = this.cesiumViewer?.dataSources?.getByName(this.dataSourceName);
      for (let i = 0; i < list.length; i++) {
        let dataSource = list[i];
        this.cesiumViewer.dataSources.remove(dataSource);
      }
    }); */
    this.dataSource.show = false;
  },
  methods: {
    async getOrgList() {
      let data = await TaskInfo.listAll();
      let res = data.data;
      const config = {
        id: "id",
        parentId: "parentId",
        childrenList: "children",
      };
      const childrenListMap = {};
      const nodeIds = {};
      const tree = [];

      for (const d of res) {
        const parentId = d[config.parentId];
        if (childrenListMap[parentId] == null) {
          childrenListMap[parentId] = [];
        }
        nodeIds[d[config.id]] = d;
        childrenListMap[parentId].push(d);
      }

      for (const d of res) {
        const parentId = d[config.parentId];
        if (nodeIds[parentId] == null) {
          tree.push(d);
        }
      }

      for (const t of tree) {
        adaptToChildrenList(t);
      }

      function adaptToChildrenList(o) {
        if (childrenListMap[o[config.id]] !== null) {
          o[config.childrenList] = childrenListMap[o[config.id]];
        }
        if (o[config.childrenList]) {
          for (const c of o[config.childrenList]) {
            adaptToChildrenList(c);
          }
        }
      }
      this.orgList = tree;
    },
    convertToSeconds(timeString) {
    const regex = /(\d+)\s*(小时|分钟|秒)/g;
    let totalSeconds = 0;
    let match;

    while ((match = regex.exec(timeString)) !== null) {
        const value = parseInt(match[1], 10);
        const unit = match[2];

        switch (unit) {
            case '小时':
                totalSeconds += value * 3600; // 1小时 = 3600秒
                break;
            case '分钟':
                totalSeconds += value * 60; // 1分钟 = 60秒
                break;
            case '秒':
                totalSeconds += value; // 直接加秒
                break;
        }
    }

    return totalSeconds;
},
    changeNode() {
      this.$refs.CascaderRef.dropDownVisible = false;
    },
    // 保存航线
    async onSave() {
      if (!this.name) {
        this.$message.warning("请输入航线名称");
        return;
      }
      if (!this.departmentId) {
        this.$message.warning("请选择所属机构");
        return;
      }
      if (this.form.length === 0) {
        this.$message.warning("请点击地图选择航点");
        return;
      }
      let waypoints = this.form.map((val) => {
        let actions = val.actions.map((item) => {
          let ret = {
            actionType: item.actionType,
          };
          if (item.param1) {
            ret.param1 = item.param1;
          }
          if (item.param2) {
            ret.param2 = item.param2;
          }
          if (item.param3) {
            ret.param3 = item.param3;
          }
          if (item.param4) {
            ret.param4 = item.param4;
          }

          return ret;
        });
        return {
          altitude: val.altitude,
          coordinate: {
            latitude: val.latitude,
            longitude: val.longitude,
          },
          frame: 3,
          speed: val.speed,
          stay: 0,
          waypointActions: actions,
        };
      });
      //标准化里创建
      let airway = {
        content: waypoints,
        distance: this.distance,
        dutyOrganizationId: "",
        departmentId: this.departmentId,
        name: this.name,
        speed: this.form[0].speed,
        flyTime: this.convertToSeconds(this.time)
      };
      try {
        let res = await AirLine.add({
          flightName: airway.name || `${this.userInfo.username}-巡查}`,
          pointCount: airway.content.length,
          distance: airway.distance,
          departmentId: airway.departmentId,
          sourceType: 1,
          flyTime:airway.flyTime,
          linePointSaveReqVOS: airway.content.map((point) => ({
            latitude: point.coordinate.latitude,
            longitude: point.coordinate.longitude,
            altitude: point.altitude,
            speed: point.speed,
            pointActionSaveReqVOS: point.waypointActions.map((action) => {
              let actionValue = [];
              action.param1 && actionValue.push(`param1:${action.param1 || ""}`);
              action.param2 && actionValue.push(`param2:${action.param2 || ""}`);
              action.param3 && actionValue.push(`param3:${action.param3 || ""}`);
              action.param4 && actionValue.push(`param4:${action.param4 || ""}`);
              return {
                actionType: action.actionType,
                actionValue: actionValue.join(";"),
              };
            }),
          })),
          nestId: this.hangar.id,
        });
        this.$message.success("创建航线成功");
        this.$emit("addDone", res.data);
        this.$emit("close");
      } catch (e) { }
      this.saveLoading = false;

      // 通过事件创建会出现重复创建的情况, 改为标准化里创建
      /* this.rootNode.$emit("airwayAdd", {
        airway: {
          content: waypoints,
          distance: this.distance,
          dutyOrganizationId: "",
          name: this.name,
          speed: this.form[0].speed,
        },
        hangar: this.hangar,
        callback: (data) => {
          this.$emit("addDone", data.id);
          this.$emit("close");
        },
      }); */
    },
    /**
     * 动作保存
     */
    onActionsSave(actions) {
      this.curForm.actions = actions;
      this.showActions = false;
    },
    /**
     * 刷新所有点,线,标签
     */
    refreshPointLineLabel() {
      this.distance = 0;
      this.dataSource.entities.removeAll();
      this.form.forEach((item, i) => {
        let position = item.position;
        let uuid = item.uuid;

        if (this.form.length > 1 && i > 0) {
          let before = this.form[i - 1].position;
          let after = position;
          this.curForm.distance = this.createLabel(uuid, before, after);
        }

        this.createPoint(uuid, position);
      });

      // 航线
      this.dataSource.entities.add({
        polyline: {
          material: Cesium.Color.RED,
          width: 3,
          positions: new Cesium.CallbackProperty(() => {
            return this.positions.map((item) => {
              let wgs84 = Utils.transformCartesian2WGS84(item);
              return Utils.transformWGS842Cartesian({
                lng: wgs84.lng,
                lat: wgs84.lat,
                alt: wgs84.alt + 10,
              });
            });
          }, false),
        },
      });
    },
    /**
     * 删除航点
     */
    onDel() {
      if (this.pageIndex > 0) {
        this.positions.splice(this.pageIndex - 1, 1);
        let delForm = this.form.splice(this.pageIndex - 1, 1)[0];
        this.pageIndex = Math.max(
          Math.min(this.pageCount, 1),
          this.pageIndex - 1
        );
        let viewer = this.cesiumViewer;
        this.refreshPointLineLabel();
      }
    },
    /**
     * 上一航点
     */
    onPrev() {
      if (this.pageIndex > 0) {
        this.pageIndex = Math.max(1, this.pageIndex - 1);
        let position = Utils.transformWGS842Cartesian({
          lng: this.curForm.longitude,
          lat: this.curForm.latitude,
          alt: 10000,
        });
        this.cesiumViewer.camera.flyTo({
          destination: position,
        });
      }
    },
    /**
     * 下一航点
     */
    onNext() {
      if (this.pageIndex < this.pageCount) {
        this.pageIndex = Math.min(this.pageCount, this.pageIndex + 1);
        let position = Utils.transformWGS842Cartesian({
          lng: this.curForm.longitude,
          lat: this.curForm.latitude,
          alt: 10000,
        });
        this.cesiumViewer.camera.flyTo({
          destination: position,
        });
      }
    },
    /**
     * 地图取点事件
     */
    async onPickPoint(movement) {
      let viewer = this.cesiumViewer;
      let entities = this.dataSource.entities;
      let windowPosition = movement.position;
      let pickedObject = viewer.scene.pick(windowPosition);
      if (pickedObject) {
        console.log("pickedObject", JSON.stringify(pickedObject.id.id));
      }
      if (
        Cesium.defined(pickedObject) &&
        pickedObject.id?.name === "airline_point"
      ) {
      } else {
        // 航点添加
        let position = Utils.getCartesian3FromPX(viewer, movement.position);
        if (Cesium.defined(position)) {
          let wgs84 = Utils.transformCartesian2WGS84(position);

          let address = await Map.Regeo({
            lon: wgs84.lng,
            lat: wgs84.lat,
            ver: 1,
          });

          // 是否取地址中
          if (this.isPickAddress) {
            if (address) {
              this.isPickAddress = false;
              this.curForm.address = address;
              this.curForm.longitude = wgs84.lng;
              this.curForm.latitude = wgs84.lat;
              this.curForm.position = position;
              this.positions[this.pageIndex - 1] = position;
              this.refreshPointLineLabel();
            }
          } else {
            let form = this.formAdd();
            let uuid = form.uuid;
            this.pageIndex++;
            this.positions.push(position);

            if (address) {
              form.address = address;
            }

            form.longitude = wgs84.lng;
            form.latitude = wgs84.lat;
            form.position = position;

            if (this.positions.length > 1) {
              let before = this.positions[this.positions.length - 2];
              let after = this.positions[this.positions.length - 1];

              form.distance = this.createLabel(uuid, before, after);
            }
            this.createPoint(uuid, position);
          }
        }
      }
    },
    /**
     * 选取航线初始化
     */
    async pickerPointInit() {
      if (this.handler) {
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN);
      }
    },
    /**
     * 创建航点
     */
    createPoint(uuid, position) {
      let wgs84 = Utils.transformCartesian2WGS84(position);
      if (this.dataSource) {
        let entities = this.dataSource.entities;
        entities.add({
          name: "airline_point",
          id: uuid,
          position: Utils.transformWGS842Cartesian({
            lng: wgs84.lng,
            lat: wgs84.lat,
            alt: wgs84.alt + 10,
          }),
          point: {
            pixelSize: 20,
            color: Cesium.Color.RED,
            fillColor: Cesium.Color.RED,
            // heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND, // supermap版本会导致拖动显示错误
          },
          label: {
            text: new Cesium.CallbackProperty(() => {
              let index = this.form.findIndex((item) => item.uuid === uuid);
              return String(index + 1);
            }, false),
            scale: 0.5,
            font: "bold 24px Microsoft YaHei",
            fillColor: Cesium.Color.WHITE,
            horizontalOrigin: Cesium.VerticalOrigin.CENTER,
            verticalOrigin: Cesium.VerticalOrigin.CENTER,
            disableDepthTestDistance: Number.POSITIVE_INFINITY,
            showBackground: false,
            outlineWidth: 0,
          },
        });
      }
    },
    /**
     * 创建航点标签
     */
    createLabel(uuid, before, after, alt) {
      if (this.dataSource) {
        let entities = this.dataSource.entities;
        let before_wgs84 = Utils.transformCartesian2WGS84(before);
        let after_wgs84 = Utils.transformCartesian2WGS84(after);

        let center_lng = (before_wgs84.lng + after_wgs84.lng) / 2;
        let cetner_lat = (before_wgs84.lat + after_wgs84.lat) / 2;
        let alt = (after_wgs84.alt + before_wgs84.alt) / 2;

        let position = Utils.transformWGS842Cartesian({
          lng: center_lng,
          lat: cetner_lat,
          alt: alt + 10,
        });
        let distance = Number(
          Cesium.Cartesian3.distance(before, after).toFixed(2)
        );
        let text = `${distance} m`;

        entities.add({
          id: `label_${uuid}`,
          position: position,
          label: {
            text: text,
            scale: 0.5,
            font: "bold 30px Microsoft YaHei",
            fillColor: Cesium.Color.fromCssColorString("#fff"),
            horizontalOrigin: Cesium.VerticalOrigin.CENTER,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            disableDepthTestDistance: Number.POSITIVE_INFINITY,
            showBackground: true,
            backgroundPadding: new Cesium.Cartesian2(10, 10),
          },
        });

        return distance;
      }
    },
    /**
     * 地理查询
     */
    onAddressInput(address, cb) {
      Map.Geo({
        keyWord: address,
        level: 12,
        // specify: "156320900",
        mapBound: "-180,-90,180,90",
        queryType: 1,
        start: 0,
        count: 10,
      })
        .then((res) => {
          cb(res.data.data.rows);
        })
        .catch((e) => cb([]));
    },
    // 表单位置信息索引
    onAddressChange(item, type) {
      if (item) {
        let location = item.lonlat.split(",");
        this.curForm.address = item.name;
        this.curForm.longitude = Number(location[0]);
        this.curForm.latitude = Number(location[1]);

        let viewer = this.cesiumViewer;
        let position = Utils.transformWGS842Cartesian({
          lng: this.curForm.longitude,
          lat: this.curForm.latitude,
          alt: Number(this.curForm.altitude),
        });

        this.curForm.position = position;
        this.positions[this.pageIndex - 1] = position;
        this.refreshPointLineLabel();
        let position1 = Utils.transformWGS842Cartesian({
          lng: this.curForm.longitude,
          lat: this.curForm.latitude,
          alt: 10000,
        });
        viewer.camera.flyTo({
          destination: position1,
        });
      }
    },
    // 点击表单旁图标定位
    async onPickAddress(type) {
      this.isPickAddress = true;
    },
    formAdd() {
      let altitude = this.curForm.altitude;
      let form = new Airway();
      //继承上一个点的高度
      form.altitude = altitude;
      this.form.push(form);
      return form;
    },
  },
};
</script>

<style lang="scss" scoped>
.airway-edit {
  position: absolute;
  top: 0px;
  width: 351px;
  z-index: 2;

  .dialog-content {
    display: flex;
    flex-direction: column;

    .ae-page {
      flex-shrink: 0;
      display: flex;
      justify-content: space-around;
      margin-bottom: 16px;
      margin-top: 16px;
    }

    .ae-form {
      flex: auto;
    }

    .ae-btns {
      text-align: right;
    }
  }
}
</style>