<script setup lang="ts">
import icon_add_outlined from '@/assets/svg/icon_add_outlined.svg'
import DeResourceTree from '@/views/common/DeResourceTree.vue'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import ArrowSide from '@/views/common/DeResourceArrow.vue'
import { nextTick, onBeforeMount, reactive, ref, computed, onMounted } from 'vue'
import PreviewHead from '@/views/data-visualization/PreviewHead.vue'
import EmptyBackground from '@/components/empty-background/src/EmptyBackground.vue'
import { storeToRefs } from 'pinia'
import { useAppStoreWithOut } from '@/store/modules/app'
import {
  getMapElementIds,
  initCanvasData,
  initCanvasDataPrepare,
  onInitReady
} from '@/utils/canvasUtils'
import { useMoveLine } from '@/hooks/web/useMoveLine'
import { Icon } from '@/components/icon-custom'
import { download2AppTemplate, downloadCanvas2 } from '@/utils/imgUtils'
import MultiplexPreviewShow from '@/views/data-visualization/MultiplexPreviewShow.vue'
import DvPreview from '@/views/data-visualization/DvPreview.vue'
import AppExportForm from '@/components/de-app/AppExportForm.vue'
import { ElMessage } from 'element-plus-secondary'
import { useEmitt } from '@/hooks/web/useEmitt'

import { useUserStoreWithOut } from '@/store/modules/user'
import { useI18n } from '@/hooks/web/useI18n'
import {
  exportLogApp,
  exportLogImg,
  exportLogPDF,
  exportLogTemplate
} from '@/api/visualization/dataVisualization'
import { deepCopy } from '@/utils/utils'
const userStore = useUserStoreWithOut()

const userName = computed(() => userStore.getName)
const { t } = useI18n()

const dvMainStore = dvMainStoreWithOut()
const { dvInfo, canvasViewDataInfo } = storeToRefs(dvMainStore)
const previewCanvasContainer = ref(null)
const dvPreviewRef = ref(null)
const slideShow = ref(true)
const dataInitState = ref(true)
const downloadStatus = ref(false)
const { width, node } = useMoveLine('DASHBOARD')
const appExportFormRef = ref(null)
const props = defineProps({
  showPosition: {
    required: false,
    type: String,
    default: 'preview'
  },
  noClose: {
    required: false,
    type: Boolean,
    default: false
  },
  resourceTable: {
    required: false,
    type: String,
    default: 'core'
  }
})

const resourceTreeRef = ref()

const hasTreeData = computed(() => {
  return resourceTreeRef.value?.hasData
})

const mounted = computed(() => {
  return resourceTreeRef.value?.mounted
})

const rootManage = computed(() => {
  return resourceTreeRef.value?.rootManage
})
const appStore = useAppStoreWithOut()

const isDataEaseBi = computed(() => appStore.getIsDataEaseBi)

function createNew() {
  resourceTreeRef.value?.createNewObject()
}

const loadCanvasData = (dvId, weight?, ext?) => {
  const initMethod = props.showPosition === 'multiplexing' ? initCanvasDataPrepare : initCanvasData
  dataInitState.value = false
  initMethod(
    dvId,
    { busiFlag: 'dataV', resourceTable: 'core' },
    function ({
      canvasDataResult,
      canvasStyleResult,
      dvInfo,
      canvasViewInfoPreview,
      curPreviewGap
    }) {
      dvInfo['weight'] = weight
      dvInfo['ext'] = ext || 0
      state.canvasDataPreview = canvasDataResult
      state.canvasStylePreview = canvasStyleResult
      state.canvasViewInfoPreview = canvasViewInfoPreview
      state.dvInfo = dvInfo
      state.curPreviewGap = curPreviewGap
      dataInitState.value = true
      // 修复铺满全屏模版导出错位问题
      if (props.showPosition !== 'multiplexing') {
        state.canvasDataPreviewSource = deepCopy(canvasDataResult)
        state.canvasStylePreviewSource = deepCopy(canvasStyleResult)
      }

      if (props.showPosition === 'preview') {
        dvMainStore.updateCurDvInfo(dvInfo)
        nextTick(() => {
          dvPreviewRef.value?.restore()
        })
      }
      nextTick(() => {
        onInitReady({ resourceId: dvId })
      })
    }
  )
}
const download = type => {
  downloadStatus.value = true
  const mapElementIds = getMapElementIds(state.canvasDataPreview)
  mapElementIds.forEach(id => useEmitt().emitter.emit('l7-prepare-picture', id))
  setTimeout(() => {
    const vueDom = previewCanvasContainer.value.querySelector('.canvas-container')
    downloadCanvas2(type, vueDom, state.dvInfo.name, () => {
      downloadStatus.value = false
      const param = {
        id: state.dvInfo.id,
        type: state.dvInfo.type === 'dashboard' ? 'panel' : 'screen'
      }
      type === 'img' ? exportLogImg(param) : exportLogPDF(param)
      mapElementIds.forEach(id => useEmitt().emitter.emit('l7-unprepare-picture', id))
    })
  }, 200)
}
const fileDownload = (downloadType, attachParams) => {
  downloadStatus.value = true
  const mapElementIds = getMapElementIds(state.canvasDataPreview)
  mapElementIds.forEach(id => useEmitt().emitter.emit('l7-prepare-picture', id))
  setTimeout(() => {
    const vueDom = previewCanvasContainer.value.querySelector('.canvas-container')
    download2AppTemplate(downloadType, vueDom, state.dvInfo.name, attachParams, () => {
      downloadStatus.value = false
      const param = {
        id: state.dvInfo.id,
        type: state.dvInfo.type === 'dashboard' ? 'panel' : 'screen'
      }
      downloadType === 'app' ? exportLogApp(param) : exportLogTemplate(param)
      mapElementIds.forEach(id => useEmitt().emitter.emit('l7-unprepare-picture', id))
    })
  }, 1000)
}

const downloadAsAppTemplate = downloadType => {
  if (downloadType === 'template') {
    fileDownload(downloadType, null)
  } else if (downloadType === 'app') {
    downLoadToAppPre()
  }
}

const downLoadToAppPre = () => {
  const result = checkTemplate()
  if (result && result.length > 0) {
    ElMessage.warning(`当前仪表板中[${result}]属于模版图表,无法导出,请先设置数据集!`)
  } else {
    appExportFormRef.value.init({
      appName: state.dvInfo.name,
      icon: null,
      version: '2.0',
      creator: userName.value,
      required: '2.9.0',
      description: null
    })
  }
}
const checkTemplate = () => {
  let templateViewNames = ','
  Object.keys(canvasViewDataInfo.value).forEach(key => {
    const viewInfo = canvasViewDataInfo.value[key]
    if (viewInfo && viewInfo?.dataFrom === 'template') {
      templateViewNames = templateViewNames + viewInfo.title + ','
    }
  })
  return templateViewNames.slice(1)
}

const slideOpenChange = () => {
  slideShow.value = !slideShow.value
}

const reload = id => {
  loadCanvasData(id, state.dvInfo.weight, state.dvInfo.ext)
}

const resourceNodeClick = data => {
  loadCanvasData(data.id, data.weight, data.ext)
}

const dataVKeepSize = computed(() => {
  return state.canvasStylePreview?.screenAdaptor === 'keep'
})

const state = reactive({
  canvasDataPreviewSource: null,
  canvasStylePreviewSource: null,
  canvasDataPreview: null,
  canvasStylePreview: null,
  canvasViewInfoPreview: null,
  dvInfo: null,
  curPreviewGap: 0
})

const sideTreeStatus = ref(true)
const changeSideTreeStatus = val => {
  sideTreeStatus.value = val
}

const mouseenter = () => {
  appStore.setArrowSide(true)
}

const mouseleave = () => {
  appStore.setArrowSide(false)
}

const getPreviewStateInfo = () => {
  return state
}

const downLoadApp = appAttachInfo => {
  fileDownload('app', appAttachInfo)
}

onMounted(() => {
  useEmitt({
    name: 'canvasDownload',
    callback: function () {
      download('img')
    }
  })
})

defineExpose({
  getPreviewStateInfo
})

onBeforeMount(() => {
  if (props.showPosition === 'preview') {
    dvMainStore.canvasDataInit()
  }
})
</script>

<template>
  <div class="dv-preview">
    <ArrowSide
      v-if="!noClose"
      :style="{ left: (sideTreeStatus ? width - 12 : 0) + 'px' }"
      @change-side-tree-status="changeSideTreeStatus"
      :isInside="!sideTreeStatus"
    ></ArrowSide>
    <el-aside
      class="resource-area"
      @mouseenter="mouseenter"
      @mouseleave="mouseleave"
      :class="{ 'close-side': !slideShow, retract: !sideTreeStatus }"
      ref="node"
      :style="{ width: width + 'px' }"
    >
      <ArrowSide
        v-if="!noClose"
        :isInside="!sideTreeStatus"
        :style="{ left: (sideTreeStatus ? width - 12 : 0) + 'px' }"
        @change-side-tree-status="changeSideTreeStatus"
      ></ArrowSide>
      <de-resource-tree
        ref="resourceTreeRef"
        v-show="slideShow"
        :cur-canvas-type="'dataV'"
        :show-position="showPosition"
        :resource-table="resourceTable"
        @node-click="resourceNodeClick"
      />
    </el-aside>
    <el-container
      class="preview-area"
      :class="{ 'no-data': !state.dvInfo?.id }"
      v-loading="!dataInitState"
    >
      <div @click="slideOpenChange" class="flexible-button-area" v-if="false">
        <el-icon v-if="slideShow"><ArrowLeft /></el-icon>
        <el-icon v-else><ArrowRight /></el-icon>
      </div>
      <template v-if="dvInfo.name">
        <preview-head
          v-if="showPosition === 'preview'"
          @reload="reload"
          @download="download"
          @downloadAsAppTemplate="downloadAsAppTemplate"
        />
        <div
          v-if="showPosition === 'multiplexing' && dataInitState"
          class="content multiplexing-content"
        >
          <multiplex-preview-show
            :component-data="state.canvasDataPreview"
            :canvas-style-data="state.canvasStylePreview"
            :canvas-view-info="state.canvasViewInfoPreview"
            :dv-info="state.dvInfo"
          ></multiplex-preview-show>
        </div>
        <div
          v-if="showPosition === 'preview'"
          :class="{ 'canvas_keep-size': dataVKeepSize }"
          ref="previewCanvasContainer"
          class="content"
        >
          <dv-preview
            ref="dvPreviewRef"
            v-if="state.canvasStylePreview && dataInitState"
            :show-position="showPosition"
            :canvas-data-preview="state.canvasDataPreview"
            :canvas-style-preview="state.canvasStylePreview"
            :canvas-view-info-preview="state.canvasViewInfoPreview"
            :dv-info="state.dvInfo"
            :cur-preview-gap="state.curPreviewGap"
            :download-status="downloadStatus"
          ></dv-preview>
        </div>
      </template>
      <template v-else-if="hasTreeData && mounted">
        <empty-background
          v-if="dataInitState"
          :description="t('visualization.select_screen_tips')"
          img-type="select"
        />
      </template>
      <template v-else-if="mounted">
        <empty-background
          v-if="dataInitState"
          :description="t('visualization.no_screen')"
          img-type="none"
        >
          <el-button v-if="rootManage && !isDataEaseBi" @click="createNew" type="primary">
            <template #icon>
              <Icon name="icon_add_outlined"><icon_add_outlined class="svg-icon" /></Icon>
            </template>
            {{ t('commons.create') }}{{ t('work_branch.big_data_screen') }}
          </el-button>
        </empty-background>
      </template>
    </el-container>
  </div>
  <app-export-form
    ref="appExportFormRef"
    :dv-info="state.dvInfo"
    :component-data="state.canvasDataPreview"
    :canvas-view-info="state.canvasViewInfoPreview"
    @downLoadApp="downLoadApp"
  ></app-export-form>
</template>

<style lang="less">
.dv-preview {
  width: 100%;
  height: 100%;
  overflow: hidden;
  display: flex;
  background: #ffffff;
  position: relative;
  .resource-area {
    position: relative;
    height: 100%;
    width: 279px;
    padding: 0;
    overflow: visible;
    border-right: 1px solid #d7d7d7;

    &.retract {
      display: none;
    }
  }
  .preview-area {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow-x: hidden;
    overflow-y: auto;
    position: relative;
    //transition: 0.5s;

    &.no-data {
      background-color: rgba(245, 246, 247, 1);
    }

    .content {
      flex: 1;
      width: 100%;
      overflow-x: hidden;
      overflow-y: auto;
      align-items: center;
    }
  }
}

.close-side {
  width: 0px !important;
  padding: 0px !important;
  border-right: 0px !important;
}

.flexible-button-area {
  position: absolute;
  height: 60px;
  width: 16px;
  left: 0;
  top: calc(50% - 30px);
  background-color: #ffffff;
  border-radius: 0 4px 4px 0;
  cursor: pointer;
  z-index: 10;
  display: flex;
  align-items: center;
  border-top: 1px solid #d7d7d7;
  border-right: 1px solid #d7d7d7;
  border-bottom: 1px solid #d7d7d7;
}

.multiplexing-content {
  padding: 12px;
  background-color: rgb(245, 246, 247);
}
</style>