<template>
  <div class="code-editor">
    <div v-if="dataArr.length === 0" class="nocode">
      <div>
        <img :src="nocode" alt="" />
        <p>编辑模板文件</p>
        <p>从左侧边栏中选择一个文件以开始编辑</p>
      </div>
    </div>
    <div v-if="dataArr.length > 0" class="close-all">
      <el-dropdown @command="CloseAll(0)">
        <span class="el-dropdown-link">
          <i class="el-icon-arrow-down el-icon-more" />
        </span>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item>关闭全部</el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
    </div>
    <el-tabs
      v-if="data.open && dataArr.length > 0"
      v-model="tabName"
      type="border-card"
      closable
      :class="`${theme}__tabs`"
      @tab-click="tabClick"
      @tab-remove="handleTabRemove"
    >
      <el-tab-pane v-for="item in dataArr" :key="item.key" :label="item.name" :name="item.key">
        <span slot="label">
          <img :src="iconSrc(item.language)" />
          {{ item.name }}
          <a v-show="item.edit" class="edits">●</a>
        </span>
        <div v-if="item.key === data.key" class="monaco-box" style="flex-wrap: wrap;">
          <img
            v-if="/\.(gif|jpg|jpeg|png|GIF|JPG|PNG)$/.test(item.name)"
            :src="`${item.src}`"
            style="max-height: 100%; max-width: 100%;"
          />
          <template v-else>
            <p v-if="!item.isRead" v-loading="!item.isRead" />
            <x-monaco-editor
              v-else
              :ref="item.key"
              :item="item"
              @onCodeChange="OnCodeChange"
              @onCodeSave="onCodeSave"
            />
          </template>
        </div>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>
<script>
import axios from "axios";
import { mapGetters, mapMutations } from "vuex";
import { getFileUrl, saveFile } from '@/api/code';
import md5 from 'crypto-js/md5'

import {
  getData,
  getDataArr,
  setDataArr,
  removeData,
  removeDataArr,
} from "@/utils/auth";

let _beforeUnload_time = 0,
    _gap_time = 0;

export default {
  name: "Code",
  data() {
    return {
      isSave: false,
      fullScreen: require('@/assets/images/code/fullscreenenter.svg'),
      cancelFullScreen: require('@/assets/images/code/cancel-full-screen.svg'),
      editDialog: false,
      scratch: false,
      currentScratch: 'current',
      options: [],
      nocode: require('@/assets/images/code.svg'),
      number: ''
    };
  },
  computed: {
    ...mapGetters(["data", "dataArr", "theme", "isFullScreen", "openFileKey", "codes"]),
    tabName: {
      get() {
        return this.data.key;
      },
      set(val) {
        let data = this.dataArr.find((e) => {
          return e.key === val;
        });
        this.SET_DATA(data);
      },
    },
    screenIcon() {
      return this.isFullScreen ? this.cancelFullScreen : this.fullScreen
    }
  },
  mounted() {
    window.onbeforeunload = function () {
      _beforeUnload_time = new Date().getTime();
    };
    window.onunload = function () {
      _gap_time = new Date().getTime() - _beforeUnload_time;
      if (_gap_time <= 5) {
        removeData();
        removeDataArr();
      }
    };
  },
  created() {
    this.number = this.$route.params && this.$route.params.id
    this.getList();
    window.addEventListener("beforeunload", (e) => this.beforeunloadHandler(e));
  },
  destroyed() {
    this.$store.commit('SET_IS_FULL_SCREEN', false)
    window.removeEventListener("beforeunload", (e) =>
      this.beforeunloadHandler(e)
    );
  },
  beforeRouteLeave(to, from, next) {
    this.$store.commit('SET_IS_FULL_SCREEN', false)
    next()
  },
  methods: {
    ...mapMutations([
      "SET_DATA",
      "SET_DATA_ARR",
      "SET_THEME",
      "CLEAR_DATA_ARR",
      "UPDATE_DATA_ARR",
      "SET_PROJECT_NAME"
    ]),
    getList() {
      // 打开之前文件
      let currentData = getData();
      let nodeArr = getDataArr();
      if (nodeArr !== null) {
        let fileArr = JSON.parse(nodeArr);
        if (fileArr.length > 0 && fileArr[this.number].length > 0) {
          let imgs = fileArr[this.number].filter((item) =>
            /\.(gif|jpg|jpeg|png|GIF|JPG|PNG)$/.test(item.name)
          );
          let Arr = fileArr[this.number].filter(
            (item) => !/\.(gif|jpg|jpeg|png|GIF|JPG|PNG)$/.test(item.name)
          );
          let focusData = {};
          let resArr = [];
          //并发请求打开页面
          axios.all(this.getPath(Arr).map(item => {
            return item.catch(err => err)
          })).then(
            axios.spread((...response) => {
              resArr = this.$_.map(response);
              let newArr = []
              for (let i = 0; i < Arr.length; i++) {
                if (resArr[i].data) {
                  Arr[i].codes = resArr[i].data.data;
                  Arr[i].mtime = resArr[i].data.mtime;
                  Arr[i].isRead = true;
                  if (currentData === Arr[i].key) {
                    focusData = Arr[i];
                    Arr[i].open = true;
                  }
                  newArr.push(Arr[i])
                }
              }
              if (!focusData.key) {
                for (let n = 0; n < imgs.length; n++) {
                  if (currentData === imgs[n].key) {
                    focusData = imgs[n];
                    imgs[n].open = true;
                  }
                }
              }


              newArr = newArr.concat(imgs);
              fileArr[this.number] = newArr;
              setDataArr(JSON.stringify(fileArr));
              this.$store.commit("SET_DATA_ARR", newArr);
              if (focusData.key) {
                this.$store.commit("SET_DATA", focusData);
              } else {
                this.$store.commit("SET_DATA", Arr[0]);
              }
            })
          )
        }
      }
    },
    getPath(Arr) {
      let Arrs = [];
      Arr.map((item) => {
        Arrs.push(
          this.$request.get(getFileUrl({key: item.key, themeId: item.number}))
        );
      });
      return Arrs;
    },
    OnCodeChange(item) {
      this.UPDATE_DATA_ARR(item);
    },
    handleTabRemove(key) {
      let curTab = this.dataArr.find(item => item.key === key)

      if (curTab.edit === true) {
        this.$confirm(`是否要保存对 ${curTab.name} 的修改?`, "提示", {
          confirmButtonText: "保存",
          distinguishCancelAndClose: true,
          cancelButtonText: "不保存",
          closeOnClickModal: false,
          type: "warning",
        })
          .then(() => {
            if (this.isSave) return;
            this.isSave = true;
            // 返回一个  promise 对象，剩余操作可以接着 then 里写
            if (!(curTab.codes)) {
              this.$message({
                type: 'warning',
                message: '请填写内容',
                duration: 1000
              })
              this.isSave = false;
              return
            }
            return saveFile({
              key: key,
              value: curTab.codes,
              encodeValue: md5(curTab.codes).toString(),
              themeId: this.number,
              mtime: curTab.mtime
            });
          })
          .then(res => {
            this.$message({
              type: 'success',
              message:'修改成功！',
              duration: 1000
            })
            this.isSave = false;
            this.closeTab(key);
          })
          .catch(action => {
            // 捕获接口报错
            if (typeof action === 'object') {
              this.$message({
                type: "error",
                message: action.response.data.message,
                duration: 1000
              })
            }
            // 捕获输入框取消或则关闭事件
            if (action === 'cancel') {
              // this.editDialog = true;
              this.closeTab(key);
            }
          });
      } else {
        this.closeTab(key);
      }
      if (this.openFileKey === key) {
        this.$store.commit('SET_OPEN_FILE_KEY', '')
      }
    },
    closeTab(key) {
      let tabs = this.dataArr;
      let activeName = this.tabName;
      if (activeName === key) {
        tabs.forEach((tab, index) => {
          if (tab.key === key) {
            let nextTab = tabs[index + 1] || tabs[index - 1];
            if (nextTab) {
              activeName = nextTab.key;
            }
          }
        });
      }

      this.tabName = activeName;
      this.$store.commit('SET_OPEN_FILE_KEY', activeName)
      this.$store.commit(
        "SET_DATA_ARR",
        tabs.filter((tab) => tab.key !== key)
      );
      //删除localstorage对应tab
      let Arr = getDataArr();
      let dataArrs = JSON.parse(Arr);
      dataArrs[this.number] = dataArrs[this.number].filter((item) => item.key !== key)
      setDataArr(JSON.stringify(dataArrs));
      if (this.openFileKey === key) {
        this.$store.commit('SET_OPEN_FILE_KEY', '')
      }
    },
    async onCodeSave(data) {
      if (this.isSave) return;
      this.isSave = true;
      if (!(data.codes)) {
        this.$message({
          type: 'warning',
          message: '请填写内容',
          duration: 1000
        })
        this.isSave = false;
        return
      }
      try {
        const res = await saveFile({
          key: data.key,
          themeId: this.number,
          value: data.codes,
          encodeValue: md5(data.codes).toString(),
          mtime: data.mtime
        });

        this.isSave = false;
        data.mtime = res.data.mtime;
        data.edit = false;
        this.$store.commit("SET_DATA", data);
        this.$message({
          message: "保存成功！",
          type: "success",
          duration: 600,
        });
      } catch (err) {
        this.isSave = false;
        console.log(err)
      }
    },
    CloseAll(num) {
      if (this.dataArr[num].edit === true) {
        this.$confirm(`是否要保存对 ${this.dataArr[num].name} 的更改？`,"提示",{
            confirmButtonText: "保存",
            cancelButtonText: "不保存",
            closeOnClickModal: false,
            distinguishCancelAndClose: true,
            customClass: 'delFileMsgBox',
            type: "warning",
        }).then(() => {
            saveFile({
              key: this.dataArr[num].key,
              themeId: this.number,
              value: this.dataArr[num].codes,
              encodeValue: md5(this.dataArr[num].codes).toString(),
              mtime: this.dataArr[num].mtime
            });
            if (num < this.dataArr.length && num !== this.dataArr.length - 1) {
              setTimeout(() => {
                this.CloseAll(num + 1);
              }, 20);
            } else if (num === this.dataArr.length - 1) {
              this.$store.commit('SET_OPEN_FILE_KEY', '')
              this.CLEAR_DATA_ARR();
            }
          })
          .catch(() => {
            if (num < this.dataArr.length && num !== this.dataArr.length - 1) {
              setTimeout(() => {
                this.CloseAll(num + 1);
              }, 20);
            } else if (num === this.dataArr.length - 1) {
              this.$store.commit('SET_OPEN_FILE_KEY', '')
              this.CLEAR_DATA_ARR();
            }
          });
      } else {
        if (num < this.dataArr.length && num !== this.dataArr.length - 1) {
          setTimeout(() => {
            this.CloseAll(num + 1);
          }, 20);
        } else if (num === this.dataArr.length - 1) {
          this.$store.commit('SET_OPEN_FILE_KEY', '')
          this.CLEAR_DATA_ARR();
        }
      }
    },
    beforeunloadHandler(e) {
      for (let i = 0; i < this.dataArr.length; i++) {
        if (this.dataArr[i].edit === true) {
          e = e || window.event;
          if (e) {
            e.returnValue = "关闭提示";
          }
          return "关闭提示";
        }
      }
    },
    tabClick(e) {
      this.$store.commit('SET_OPEN_FILE_KEY', e.name)
    },
    cancelEditDialog() {
      this.editDialog = false;
      this.isSave = false;
    },
    // 显示文件和文件夹的图标
    iconSrc(src) {
      return require('@/assets/images/code/' + src + '.svg')
    },
  }
};
</script>
