<template>
  <div class="page-top-setting-wrap">
    <div class="logo-wrap item-wrap">
      <img
        class="menu-img"
        src="~packages/BigScreenDesign/images/app.png"
        alt="返回"
        @click="backManagement"
      >
      <span class="logo-text name-span">{{ pageInfo.name }}</span>
    </div>
    <div class="head-btn-group">
      <CusBtn
        v-for="(mode,index) in alignList"
        :key="mode.value"
        class="align-btn"
        @click="setAlign(mode.value)"
      >
        <icon-svg
          :name="iconList[index]"
        />
      </CusBtn>
      <CusBtn
        :loading="saveAndPreviewLoading"
        @click.native="designAssign()"
      >
        设计分工
      </CusBtn>
      <CusBtn
        @click.native="showHostory"
      >
        历史操作
      </CusBtn>
      <CusBtn
        :disabled="undoDisabled"
        @click.native="undo(true)"
      >
        <i class="iconfont-bigscreen icon-jiantouqianjin icon-reverse" />
      </CusBtn>
      <CusBtn
        :disabled="redoDisabled"
        @click.native="undo(false)"
      >
        <i class="iconfont-bigscreen icon-jiantouqianjin" />
      </CusBtn>
      <CusBtn
        :loading="saveAndPreviewLoading"
        @click.native="createdImg()"
      >
        生成图片
      </CusBtn>
      <CusBtn
        :loading="saveAndPreviewLoading"
        @click.native="execRun()"
      >
        预览
      </CusBtn>
      <CusBtn
        :loading="saveLoading"
        @click="save('saveLoading')"
      >
        保存
      </CusBtn>
      <CusBtn @click="empty">
        清空
      </CusBtn>
      <CusBtn @click="showPageInfo">
        设置
      </CusBtn>
      <CusBtn @click="updateRightVisiable">
        <i
          class="iconfont-bigscreen"
          :class="rightFold ? 'icon-zhankaicaidan' : 'icon-shouqicaidan'"
        />
      </CusBtn>
    </div>
    <ChooseTemplateDialog
      ref="ChooseTemplateDialog"
      :has-create="false"
      :page-info="pageInfo"
      @replaceItByTemplate="replaceItByTemplate"
    />
    <AssignDialog ref="AssignDialog" />
    <HistoryList ref="HistoryList" />
  </div>
</template>
<script>
import { toJpeg, toPng } from 'html-to-image'
import { mapMutations, mapActions, mapState } from 'vuex'
import { saveScreen } from 'packages/js/api/bigScreenApi'
import ChooseTemplateDialog from 'packages/BigScreenManagement/ChooseTemplateDialog.vue'
import _ from 'lodash'
import { stringifyObjectFunctions } from 'packages/js/utils/evalFunctions'
import AssignDialog from 'packages/BigScreenDesign/AssignDialog/index.vue'
import HistoryList from 'packages/BigScreenDesign/HistoryList/index.vue'
import CusBtn from './BtnLoading'
import icons from 'packages/assets/images/alignIcon/export'
import IconSvg from 'packages/SvgIcon'
import {
  showSize,
  dataURLtoBlob,
  translateBlobToBase64
} from 'packages/js/utils/compressImg'
import * as imageConversion from 'image-conversion'
export default {
  name: 'PageTopSetting',
  components: {
    IconSvg,
    ChooseTemplateDialog,
    AssignDialog,
    CusBtn,
    HistoryList
  },
  props: {
    code: {
      type: String,
      default: ''
    },
    rightFold: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      iconList: icons.getNameList(),
      alignList: [
        {
          label: '左侧对齐',
          value: 'left'
        },
        {
          label: '居中对齐',
          value: 'center'
        },
        {
          label: '右侧对齐',
          value: 'right'
        },
        {
          label: '顶部对齐',
          value: 'top'
        },
        {
          label: '中部对齐',
          value: 'middle'
        },
        {
          label: '底部对齐',
          value: 'bottom'
        },
        {
          label: '水平均分',
          value: 'levelAround'
        },
        {
          label: '垂直均分',
          value: 'verticalAround'
        }
      ],
      appInfo: '',
      saveLoading: false,
      createdImgLoading: false,
      saveAndPreviewLoading: false
    }
  },
  computed: {
    ...mapState({
      pageInfo: (state) => state.bigScreen.pageInfo,
      timelineStore: (state) => state.bigScreen.timelineStore,
      currentTimeLine: (state) => state.bigScreen.currentTimeLine,
      activeCodes: state => state.bigScreen.activeCodes
    }),
    pageCode () {
      return this.$route.query.code || this.code
    },
    undoDisabled () {
      return Boolean(this.currentTimeLine <= 1)
    },
    redoDisabled () {
      return Boolean(
        !this.timelineStore?.length ||
        (
          this.currentTimeLine &&
          this.currentTimeLine === this.timelineStore?.length
        )
      )
    }
  },
  methods: {
    ...mapActions({
      initLayout: 'bigScreen/initLayout'
    }),
    ...mapMutations({
      changeActiveCode: 'bigScreen/changeActiveCode',
      changeActiveItem: 'bigScreen/changeActiveItem',
      changePageInfo: 'bigScreen/changePageInfo',
      undoTimeLine: 'bigScreen/undoTimeLine',
      saveTimeLine: 'bigScreen/saveTimeLine'
    }),
    setAlign (command) {
      debugger
      const pageInfo = _.cloneDeep(this.pageInfo)
      // 获取所有选中的组件
      let activeChartList = pageInfo.chartList.filter((chart) => {
        return this.activeCodes.some(code => (code === chart.code))
      })
      // 找到选中组件内的xy最大最小值
      const maxXW = Math.max.apply(Math, activeChartList.map(item => { return item.x + item.w }))
      let maxX = Math.max.apply(Math, activeChartList.map(item => { return item.x }))
      const minX = Math.min.apply(Math, activeChartList.map(item => { return item.x }))
      const maxYH = Math.max.apply(Math, activeChartList.map(item => { return item.y + item.h }))
      const maxY = Math.max.apply(Math, activeChartList.map(item => { return item.y }))
      const minY = Math.min.apply(Math, activeChartList.map(item => { return item.y }))
      const centerW = maxXW - minX
      const centerH = maxY - minY
      switch (command) {
        case 'left':
          activeChartList.forEach((chart) => {
            chart.x = minX
          })
          break
        case 'center':
          // eslint-disable-next-line no-case-declarations
          activeChartList.forEach((chart) => {
            chart.x = (centerW - chart.w) / 2 + minX
          })
          break
        case 'right':
          activeChartList.forEach((chart) => {
            chart.x = maxXW - chart.w
          })
          break
        case 'top':
          activeChartList.forEach((chart) => {
            chart.y = minY
          })
          break
        case 'middle':
          activeChartList.forEach((chart) => {
            chart.y = (centerH - chart.h) / 2 + minY
          })
          break
        case 'bottom':
          activeChartList.forEach((chart) => {
            chart.y = maxYH - chart.h
          })
          break
        case 'levelAround':
          // 先让数组根据x的属性进行排序
          activeChartList = activeChartList.sort(this.compare('x'))
          // eslint-disable-next-line no-case-declarations
          const minXW = activeChartList[0].x + activeChartList[0].w
          maxX = Math.max.apply(Math, activeChartList.map(item => { return item.x }))
          // 中间总的宽度
          // eslint-disable-next-line no-case-declarations
          let totalW = 0
          for (let i = 1; i < activeChartList.length - 1; i++) {
            totalW = totalW + activeChartList[i].w
          }
          // 中间剩余的空格
          // eslint-disable-next-line no-case-declarations
          const padding = (maxX - minXW - totalW) / (activeChartList.length - 1)
          // eslint-disable-next-line no-case-declarations
          let useW = 0
          for (let i = 1; i < activeChartList.length - 1; i++) {
            activeChartList[i].x = minXW + padding * i + useW
            useW = useW + activeChartList[i].w
          }
          break
        case 'verticalAround':
          // 先让数组根据y的属性进行排序
          activeChartList = activeChartList.sort(this.compare('y'))
          // eslint-disable-next-line no-case-declarations
          const minYH = activeChartList[0].y + activeChartList[0].h
          // eslint-disable-next-line no-case-declarations
          let totalH = 0
          for (let i = 1; i < activeChartList.length - 1; i++) {
            totalH = totalH + activeChartList[i].h
          }
          // eslint-disable-next-line no-case-declarations
          const paddingBottom = (maxY - minYH - totalH) / (activeChartList.length - 1)
          // eslint-disable-next-line no-case-declarations
          let useH = 0
          for (let i = 1; i < activeChartList.length - 1; i++) {
            activeChartList[i].y = minYH + paddingBottom * i + useH
            useH = useH + activeChartList[i].h
          }
          break
      }
      pageInfo.chartList = [...pageInfo.chartList, ...activeChartList]
      pageInfo.chartList = _.uniqBy(pageInfo.chartList, 'code')
      this.changePageInfo(pageInfo)
    },
    compare (property) {
      return function (obj1, obj2) {
        const value1 = obj1[property]
        const value2 = obj2[property]
        return value1 - value2 // 升序
      }
    },
    backManagement () {
      this.$router.push({
        path: this.pageInfo.type === 'component' ? (window.BS_CONFIG?.routers?.componentUrl || '/big-screen-components') : (window.BS_CONFIG?.routers?.pageManagementUrl || '/home')
      })
    },
    undo (isUndo) {
      this.undoTimeLine(isUndo)
    },
    // 清空
    empty () {
      this.changeActiveCode('')
      this.$emit('empty')
    },
    // 预览
    async execRun () {
      this.save('saveAndPreviewLoading').then((res) => {
        this.preview()
      })
    },
    // 预览
    preview () {
      const { href } = this.$router.resolve({
        path: window.BS_CONFIG?.routers?.previewUrl || '/big-screen/preview',
        query: {
          code: this.pageCode
        }
      })
      window.open(href, '_blank')
    },
    // 保存
    save (loadingType = 'saveLoading', hasPageTemplateId = false) {
      const pageInfo = _.cloneDeep(this.handleSaveData())
      // 保存页面
      this[loadingType] = true
      return new Promise((resolve, reject) => {
        if (!hasPageTemplateId) {
          delete pageInfo.pageTemplateId
        }
        const node = document.querySelector('.render-theme-wrap')
        toJpeg(node, { quality: 0.2 })
          .then((dataUrl) => {
            const that = this
            if (showSize(dataUrl) > 200) {
              const url = dataURLtoBlob(dataUrl)
              // 压缩到500KB,这里的500就是要压缩的大小,可自定义
              imageConversion
                .compressAccurately(url, {
                  size: 200, // 图片大小压缩到100kb
                  width: 1280, // 宽度压缩到1280
                  height: 720 // 高度压缩到720
                })
                .then((res) => {
                  translateBlobToBase64(res, function (e) {
                    pageInfo.coverPicture = e.result
                    saveScreen(pageInfo)
                      .then((res) => {
                        that.$message.success('保存成功')
                        resolve(res)
                      })
                      .finally(() => {
                        that[loadingType] = false
                      })
                  })
                })
            } else {
              pageInfo.coverPicture = dataUrl
              saveScreen(pageInfo)
                .then((res) => {
                  this.$message.success('保存成功')
                  resolve(res)
                })
                .finally(() => {
                  this[loadingType] = false
                })
            }
          })
          .catch(() => {
            this[loadingType] = false
          })
      })
    },
    goBack (path) {
      this.$router.push({
        path: `/${path}`
      })
    },
    // 得到模板列表
    getTemplateList (type) {
      this.$nextTick(() => {
        this.$refs.ChooseTemplateDialog.init(undefined, type)
      })
    },
    // 选择模版后覆盖配置
    selectTemplate (template) {
      this.pageInfo.pageTemplateId = template.id
      this.save('saveLoading', true).then(() => {
        this.initLayout(this.pageCode)
      })
    },
    replaceItByTemplate (config) {
      this.changePageInfo(config)
    },
    // 处理保存数据
    handleSaveData () {
      const pageInfo = _.cloneDeep(this.pageInfo)
      const chartList = _.cloneDeep(this.pageInfo.chartList)

      pageInfo.pageConfig.cacheDataSets =
        pageInfo.pageConfig.cacheDataSets?.map((cache) => ({
          name: cache.name,
          dataSetId: cache.dataSetId
        })) || []

      const newChartList = chartList?.map((chart) => {
        // 如果是自定义组件，需要将option转换为json字符串，因为其中可能有函数
        if (['customComponent', 'remoteComponent'].includes(chart.type)) {
          chart.option.data = []
          chart.option = stringifyObjectFunctions(chart.option)
        }
        return chart
      })
      return _.cloneDeep({
        ...this.pageInfo,
        chartList: newChartList
      })
    },
    updateRightVisiable () {
      this.$emit('updateRightVisiable', !this.rightFold)
    },
    showPageInfo () {
      this.$emit('showPageInfo')
    },
    designAssign () {
      this.$refs.AssignDialog.init()
    },
    showHostory () {
      this.$refs.HistoryList.init()
    },
    createdImg () {
      this.saveAndPreviewLoading = true
      const node = document.querySelector('.render-theme-wrap')
      toPng(node)
        .then((dataUrl) => {
          const link = document.createElement('a')
          link.download = `${this.pageInfo.name}.png`
          link.href = dataUrl
          link.click()
          link.addEventListener('click', () => {
            link.remove()
          })
          this.saveAndPreviewLoading = false
        })
        .catch(() => {
          this.$message.warning('出现未知错误，请重试')
          this.saveAndPreviewLoading = false
        })
    }
  }
}
</script>
<style lang="scss" scoped>
@import '~packages/BigScreenDesign/fonts/iconfont.css';
.default-layout-box {
  display: flex;
  flex-wrap: wrap;

  .default-layout-item {
    cursor: pointer;
    width: 42%;
    margin: 9px;
    display: flex;
    flex-direction: column;
    align-items: center;

    .component-name {
      font-size: 12px;
    }

    .sampleImg {
      margin: 0 auto;
      width: 102px;
      height: 73px;
      display: block;
    }

    .img_dispaly {
      margin: 0 auto;
      text-align: center;
      width: 100px;
      height: 70px;
      line-height: 70px;
      background-color: #d7d7d7;
      color: #999;
    }

    .demonstration {
      text-align: center;
    }
  }

  .default-layout-item:hover {
    cursor: pointer;
  }

  /deep/.el-radio__label {
    display: none;
  }
}

.page-top-setting-wrap {
  height: 40px;
  background-color: var(--bs-background-2);
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: relative;
  color: #ffffff;
  padding: 0 5px;

  .app-name {
    cursor: pointer;
  }

  .head-btn-group {
    display: flex;
    margin-left: 50px;

    i {
      font-size: 14px;
    }

    .icon-reverse {
      transform: rotate(180deg);
    }
  }

  .item-wrap {
    display: flex;
    align-items: center;

    .menu-img {
      width: 18px;
      height: 18px;
      margin-left: 9px;
      margin-right: 15px;
      cursor: pointer;
    }

    .logo-text {
      user-select: none;
      margin-left: 9px;
      font-size: 14px;
      color: #ffffff;
    }

    .name-span {
      max-width: 300px;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }
}
</style>
