<script>
import { getCanvasImageAndViewPoint } from '@/utils';
import { getSceneConfig, getLayerTreeBySceneId, updateSceneConfig } from '@/api/aiSupervision/layerConfigApi';
import LayerTree from '../layerTree/index.vue';
import { addLayer, removeLayer, zoomToLayer } from '../layerTree/index.js';

let viewer = undefined;
export default {
  name: 'SceneConfig',
  components: {
    LayerTree
  },
  props: {
    sceneId: {
      type: String,
      default: ''
    },
    defaultCheckedKeys: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      activeNames: ['1', '2', '3'],
      viewForm: { image: '', lng: '', lat: '', alt: '', heading: '', pitch: '', roll: '' },
      initForm: {
        initTime: '',
        initWeather: 1,
        ambientLightIntensity: '',
        weatherIntensity: '',
        movementSensitivity: '',
        rotationSensitivity: '',
        zoomSensitivity: ''
      },
      weatherOptions: [
        { label: '晴天', value: 1 },
        { label: '多云', value: 2 },
        { label: '阴天', value: 3 },
        { label: '小雨', value: 4 },
        { label: '中雨', value: 5 },
        { label: '暴雨', value: 6 },
        { label: '雪天', value: 7 },
        { label: '雾天', value: 8 }
      ],
      isEdit: false,
      treeData: [],
      defaultProps: { children: 'children', label: 'text' },
      defaultViewProps: { children: 'children', label: 'text', disabled: this.disabledNode }
    };
  },
  methods: {
    initData() {
      this.initMap();
      this.fetchSceneConfig();
      this.fetchLayerTree();
    },
    disabledNode(data, node) {
      if (node.isLeaf) {
        const checkedKeys = this.$refs.layerTree.getCheckedKeys();
        node.checked = checkedKeys.includes(data.id);
      }
      return true;
    },
    fetchSceneConfig() {
      getSceneConfig(this.sceneId).then((res) => {
        if (res.success && res.data) {
          const {
            initTime,
            initWeather,
            ambientLightIntensity,
            weatherIntensity,
            movementSensitivity,
            rotationSensitivity,
            zoomSensitivity,
            cameraPosture,
            viewImg,
            layerId,
            id
          } = res.data;
          this.initForm.id = id;
          this.initForm.initTime = initTime;
          this.initForm.initWeather = initWeather;
          this.initForm.ambientLightIntensity = ambientLightIntensity;
          this.initForm.weatherIntensity = weatherIntensity;
          this.initForm.movementSensitivity = movementSensitivity;
          this.initForm.rotationSensitivity = rotationSensitivity;
          this.initForm.zoomSensitivity = zoomSensitivity;
          this.viewForm = JSON.parse(cameraPosture);
          this.viewForm.image = viewImg;
          const layerIds = JSON.parse(layerId);
          this.$emit('set-checked-keys', layerIds);
          this.$nextTick(() => {
            if (this.viewForm.image) {
              const { lng, lat, alt, heading, pitch, roll } = this.viewForm;
              setTimeout(() => {
                window.viewer.scene.camera.setView({
                  destination: new Cesium.Cartesian3.fromDegrees(lng, lat, alt),
                  orientation: {
                    heading,
                    pitch,
                    roll
                  }
                });
              }, 1000);
            }
          });
        }
      });
    },
    fetchLayerTree() {
      getLayerTreeBySceneId(this.sceneId).then((res) => {
        if (res.success && res.data) {
          this.treeData = this.restructTreeData([res.data]);

          this.$nextTick(() => {
            const checkedNodes = this.$refs.layerTree.getCheckedNodes(true);
            checkedNodes.forEach((node, index) => {
              this.onCheck(node);
            });
          });
        }
      });
    },
    restructTreeData(data) {
      return data.map((item) => {
        if (item.children && item.children.length) {
          item.children = this.restructTreeData(item.children);
        }
        item.children = item.children || [];
        if (item.layers && item.layers.length) {
          const layers = item.layers.map((layer) => {
            return {
              ...layer,
              children: []
            };
          });
          item.children = item.children.concat(layers);
        }
        return item;
      });
    },
    initMap() {
      viewer = new sycim.Viewer('cesiumContainer');
      window.viewer = viewer;
      let baseLayer = sycim.ImageryLayerFactory.createImageryLayer(sycim.ImageryType.ARCGIS, {
        url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
      });
      viewer.addBaseLayer(baseLayer);
    },
    fetchView() {
      const { imageSrc, position, heading, pitch, roll } = getCanvasImageAndViewPoint(viewer);
      const { lng, lat, alt } = sycim.T.transformCartesianToWGS84(position);
      this.viewForm.lng = lng;
      this.viewForm.lat = lat;
      this.viewForm.alt = alt;
      this.viewForm.heading = heading;
      this.viewForm.pitch = pitch;
      this.viewForm.roll = roll;
      this.viewForm.image = imageSrc;
    },
    handleEvent() {
      if (this.isEdit) {
        this.saveSceneConfig();
      }
      this.isEdit = !this.isEdit;
    },
    onCheck(data) {
      if (!data.iconCls) {
        // 获取树的勾选值，不一定是默认勾选的值
        const checkedKeys = this.$refs.layerTree.getCheckedKeys();
        this.handleCheckChange(data, { checkedKeys });
      }
    },
    handleCheckChange(data, checkedData) {
      const { id } = data;
      const { checkedKeys } = checkedData;
      const nodes = [data];
      if (data.children?.length > 0) {
        this.flattenTree(data.children, nodes);
      }
      const checked = checkedKeys.includes(id);
      this.toggleLayer(nodes, checked);
    },
    flattenTree(tree, flatArray = []) {
      tree.forEach((node) => {
        const { children, ...rest } = node;
        flatArray.push(rest);
        if (children && children.length > 0) {
          flattenTree(children, flatArray);
        }
      });
      return flatArray;
    },
    toggleLayer(nodes, checked) {
      if (Array.isArray(nodes)) {
        nodes.forEach((node) => {
          if (checked) {
            addLayer(node);
          } else {
            removeLayer(node);
          }
        });
      }
    },
    goPosition(node) {
      zoomToLayer(node.data);
    },
    saveSceneConfig() {
      const form = JSON.parse(JSON.stringify(this.viewForm));
      delete form.image;
      const layerId = this.$refs.layerConfigTree.getCheckedKeys();
      const params = {
        sceneId: this.sceneId,
        ...this.initForm,
        viewImg: this.viewForm.image,
        layerId: JSON.stringify(layerId),
        cameraPosture: JSON.stringify({ ...form })
      };
      updateSceneConfig(params).then((res) => {
        if (res.success) {
          this.$message.success('保存成功');
        }
      });
    },
    cancelEvent() {
      this.isEdit = false;
    }
  }
};
</script>

<template>
  <div class="box-wrapper">
    <div class="left-panel">
      <el-collapse class="sy-collapse" v-model="activeNames">
        <el-collapse-item title="初始环境配置" name="1">
          <el-form :model="initForm" label-width="100px" :disabled="!isEdit">
            <el-form-item label="时间模式" prop="initTime">
              <el-time-select
                v-model="initForm.initTime"
                :picker-options="{
                  start: '00:00',
                  step: '00:15',
                  end: '23:45'
                }"
                placeholder="选择时间"
              >
              </el-time-select>
            </el-form-item>
            <el-form-item label="天气模式" prop="initWeather">
              <el-select v-model="initForm.initWeather">
                <el-option v-for="(item, index) in weatherOptions" :label="item.label" :value="item.value"></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="环境光强度" prop="ambientLightIntensity">
              <el-input v-model="initForm.ambientLightIntensity"></el-input>
            </el-form-item>
            <el-form-item label="天气强度" prop="weatherIntensity">
              <el-input v-model="initForm.weatherIntensity"></el-input>
            </el-form-item>
            <el-form-item label="移动灵敏度" prop="movementSensitivity">
              <el-input v-model="initForm.movementSensitivity"></el-input>
            </el-form-item>
            <el-form-item label="旋转灵敏度" prop="rotationSensitivity">
              <el-input v-model="initForm.rotationSensitivity"></el-input>
            </el-form-item>
            <el-form-item label="缩放灵敏度" prop="zoomSensitivity">
              <el-input v-model="initForm.zoomSensitivity"></el-input>
            </el-form-item>
          </el-form>
        </el-collapse-item>
        <el-collapse-item title="初始视角配置" name="2">
          <el-form :model="viewForm" label-width="80px" :disabled="!isEdit">
            <el-form-item class="mix" label="缩略图" prop="image">
              <el-button v-show="isEdit" type="text" @click="fetchView">捕获当前视角</el-button>
              <el-image v-if="viewForm.image" :src="viewForm.image"></el-image>
            </el-form-item>
            <el-form-item label="视角位置"></el-form-item>
            <el-form-item label="经度" prop="lng">
              <el-input v-model="viewForm.lng"></el-input>
            </el-form-item>
            <el-form-item label="纬度" prop="lat">
              <el-input v-model="viewForm.lat"></el-input>
            </el-form-item>
            <el-form-item label="高度" prop="alt">
              <el-input v-model="viewForm.alt"></el-input>
            </el-form-item>
            <el-form-item label="偏航角" prop="heading">
              <el-input v-model="viewForm.heading"></el-input>
            </el-form-item>
            <el-form-item label="俯仰角" prop="pitch">
              <el-input v-model="viewForm.pitch"></el-input>
            </el-form-item>
            <el-form-item label="翻滚角" prop="roll">
              <el-input v-model="viewForm.roll"></el-input>
            </el-form-item>
          </el-form>
        </el-collapse-item>
        <el-collapse-item title="初始化图层配置" name="3">
          <layer-tree
            ref="layerConfigTree"
            :show-search="true"
            :show-checkbox="true"
            :default-checked-keys="defaultCheckedKeys"
            :default-props="defaultViewProps"
            :data="treeData"
          ></layer-tree>
        </el-collapse-item>
      </el-collapse>
      <div class="footer-panel">
        <el-button v-show="isEdit" class="btn" @click="cancelEvent">取 消</el-button>
        <el-button type="primary" class="btn" @click="handleEvent">{{ isEdit ? '保 存' : '编 辑' }}</el-button>
      </div>
    </div>
    <div class="right-panel">
      <div id="cesiumContainer"></div>
      <el-popover class="layer-btn" placement="left-start" width="320" trigger="click">
        <div class="layer-wrapper">
          <div class="title-box">
            <span class="title">项目图层资源目录</span>
          </div>
          <layer-tree
            ref="layerTree"
            :show-checkbox="true"
            :show-search="true"
            :show-btns="true"
            :default-checked-keys="defaultCheckedKeys"
            :data="treeData"
            :default-props="defaultProps"
            @check-change="onCheck"
            @location="goPosition"
          ></layer-tree>
        </div>
        <el-button slot="reference" icon="el-icon-menu"></el-button>
      </el-popover>
    </div>
  </div>
</template>

<style lang="less">
.layer-wrapper {
  .title-box {
    margin-bottom: 12px;
    .title {
      font-size: 16px;
    }
  }
}
</style>

<style lang="less" scoped>
.box-wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  .left-panel {
    flex: 1;
    height: 100%;
    padding: 0 12px;
    .sy-collapse {
      height: calc(100% - 50px);
      overflow: auto;
      .el-form {
        .el-form-item {
          &.mix {
            text-align: right;
            .el-form-item__content {
              display: flex;
              flex-direction: column;
              align-items: flex-end;
              .el-button {
                width: 100px;
              }
              .el-image {
                width: 100%;
                height: 300px;
              }
            }
          }
          .el-date-editor,
          .el-select {
            width: 100%;
          }
        }
      }
    }

    .footer-panel {
      height: 50px;
      line-height: 50px;
      text-align: center;
    }
  }
  .right-panel {
    position: relative;
    width: 70%;
    height: 100%;
    #cesiumContainer {
      width: 100%;
      height: 100%;
    }
    .layer-btn {
      position: absolute;
      top: 20px;
      right: 20px;
      z-index: 1;
    }
  }
}
</style>
