<template>
  <p class="desc">被 {} 包裹的为占位符，在使用时会被实际参数占用，不可去除</p>
  <div>
    <RadioGroup v-model:value="currentLang" button-style="solid">
      <RadioButton v-for="(_, name) in trees" :key="name" :value="name">{{
        name
      }}</RadioButton>
    </RadioGroup>
  </div>

  <div :key="importCount" class="langs">
    <template v-for="(tree, name) in trees">
      <div v-if="name === currentLang" :key="name">
        <Upload
          :file-list="[]"
          :max-size="100000000"
          :extnames="undefined"
          :multiple="false"
          :before-upload="file => onBeforeUpload(name, file)"
          accept=".xls"
        >
          <a>导入</a>
        </Upload>
        <a @click="exportFile(name)">导出</a>
        <Tree :tree-data="tree" default-expand-all>
          <template #title="{ dataRef }">
            <template v-if="!dataRef.children">
              {{ dataRef.label }} :
              <Textarea
                v-model:value="dataRef.title"
                :placeholder="dataRef.label"
                style="width: 300px"
              />
            </template>
            <template v-else> {{ dataRef.title }} </template>
          </template>
        </Tree>
      </div>
    </template>
  </div>

  <Button block size="large" type="primary" class="btn" @click="emit('submit')"
    >保存</Button
  >
</template>

<script setup lang="ts">
import 'ant-design-vue/dist/antd.css'
import * as XLSX from 'xlsx'
import { Lang } from './main'
import {
  Tree,
  Textarea,
  Button,
  Upload,
  message,
  RadioGroup,
  RadioButton
} from 'ant-design-vue'
import { reactive, ref } from 'vue'
import { saveAs } from '@/utils/file-serve'

// console.log(utils)
const props = defineProps<{ langs: Record<string, Lang> }>()
const emit = defineEmits<{ (e: 'submit'): void }>()

const normalLangTree = (lang: Lang, prefix = '') => {
  return Object.entries(lang)
    .map(([name, value]) => {
      const key = prefix + name
      if (typeof value === 'string') {
        return reactive({
          key,
          label: name,
          get title() {
            return lang[name]
          },
          set title(value) {
            lang[name] = value
          }
        })
      } else {
        return {
          key,
          label: '',
          title: name,
          children: normalLangTree(value, key)
        }
      }
    })
    .sort((a, b) => a.key.localeCompare(b.key))
}

const trees = Object.entries(props.langs).reduce((t, [name, lang]) => {
  t[name] = normalLangTree(lang)
  return t
}, {})
const currentLang = ref('zh')

const onBeforeUpload = (name: string, file: File) => {
  const index = file.name.lastIndexOf('.')
  const ext = ~index ? file.name.substring(index + 1).toUpperCase() : null

  if (!ext || ext !== 'XLS') {
    message.error(`仅支持xls文件格式`)
  } else {
    let reader = new FileReader()
    //读入file
    reader.readAsBinaryString(file)
    reader.onload = e => {
      importFile(props.langs[name], e.target.result)
    }
  }
  return false
}

const importCount = ref(0)
function importFile(lang: Lang, buffer: string | ArrayBuffer) {
  const workbook = XLSX.read(buffer, { type: 'binary' })
  const data = workbook.Sheets[workbook.SheetNames[0]]
  const keyKeys = Object.keys(data).filter(
    k => k.charAt(0) === 'A' && Number(k.substring(1)) > 1
  )

  for (const keyKey of keyKeys) {
    const valueKey = `B${keyKey.substring(1)}`
    const value = data[valueKey]
    const key = data[keyKey]
    const langKey: string = key?.v
    const langValue: string = value?.v

    if (!langKey || !langValue) {
      continue
    }

    const paths = langKey.split('.')
    for (let i = 0, target = lang; i < paths.length; i++) {
      const key = paths[i]
      if (key in target) {
        if (i === paths.length - 1) {
          target[key] = langValue
        } else if (typeof target[key] !== 'string') {
          target = target[key] as Lang
        }
      } else {
        break
      }
    }
  }

  importCount.value++
}

const getSheetData = (lang: Lang, prev = '') => {
  const result = []
  for (const [key, value] of Object.entries(lang)) {
    const label = (prev ? `${prev}.` : '') + key
    if (typeof value === 'string') {
      result.push({
        key: label,
        value
      })
    } else {
      result.push(...getSheetData(value, label))
    }
  }
  return result
}

function exportFile(name) {
  const sheetData = getSheetData(props.langs[name])
  // 将由对象组成的数组转化成sheet
  const sheet = XLSX.utils.json_to_sheet(sheetData)
  // 百分数和数字更改为数字类型
  Object.keys(sheet).forEach(key => {
    if (sheet[key].v) {
      const val = sheet[key].v
      if (!isNaN(val)) {
        sheet[key].t = 'n'
      }
      if (val.lastIndexOf('%') === val.length - 1) {
        sheet[key].t = 'n'
        sheet[key].z = '0.00%'
        sheet[key].v = Number(val.substring(0, val.length - 1)) / 100
      }
    }
  })
  // 创建虚拟的workbook
  const wb = XLSX.utils.book_new()
  // 把sheet添加到workbook中
  XLSX.utils.book_append_sheet(wb, sheet, name)
  const workbookBlob = workbook2blob(wb)
  saveAs(workbookBlob, `${name}.xls`)
}

function workbook2blob(workbook) {
  // 生成excel的配置项
  const wopts = {
    // 要生成的文件类型
    bookType: 'xlsx',
    // // 是否生成Shared String Table，官方解释是，如果开启生成速度会下降，但在低版本IOS设备上有更好的兼容性
    bookSST: false,
    type: 'binary'
  }
  const wbout = XLSX.write(workbook, wopts as any)
  // 将字符串转ArrayBuffer
  function s2ab(s: string) {
    const buf = new ArrayBuffer(s.length)
    const view = new Uint8Array(buf)
    for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
    return buf
  }
  const blob = new Blob([s2ab(wbout)], {
    type: 'application/octet-stream'
  })
  return blob
}
</script>

<style scoped lang="scss">
.desc {
  text-align: center;
  font-size: 1.5em;
}

h1 {
  text-align: center;
}

.langs {
  display: flex;
  padding-bottom: 80px;
}

.lang {
  flex: 1;
  padding-left: 30px;

  h2 {
    text-align: center;
    position: fixed;
    top: 50%;
    margin-left: -30px;
    display: block;
  }
}

.btn {
  position: fixed;
  bottom: 0;
  left: 0;
}
</style>
