<script setup lang="ts">
import { reactive, watch, onMounted, PropType, nextTick } from 'vue';
import { Container, Draggable } from 'vue3-smooth-dnd';
import useI18n from '@/hooks/useI18n';
import { dbGetJSON, dbSetJSON } from '@/utils/cache-db-utils';
import { CACHE_DB_TABLE_DND } from '@/constants/cache-keys-constants';
const { t, currentLocale } = useI18n();

const emit = defineEmits(['update:columns-dnd']);
const props = defineProps({
  /**
   * 表格字段列非响应式数据，必传
   *
   * v-model:columns-dnd取变更的数据
   */
  columns: {
    type: Array<any>,
    required: true,
  },
  /**
   * 按钮类型
   * text 图标
   * ghost 图标按钮带文字
   */
  type: {
    type: String as PropType<'text' | 'ghost'>,
    default: 'text',
  },
  /**
   * 缓存列变更数据标识，不传则不缓存
   */
  cacheId: {
    type: String,
    default: '',
  },
});

/**表格字段列 */
const tableColumns = reactive(props.columns);

/**表格字段列勾选状态 */
const state = reactive<{
  indeterminate: boolean;
  /**是否全选 */
  checkAll: boolean;
  /**字段标题列表 */
  columnsTitleList: string[];
}>({
  indeterminate: false,
  checkAll: true,
  columnsTitleList: [],
});

/**表格字段列全选操作 */
function fnTableColumnsCheckAllChange(e: any) {
  const checked = e.target.checked;
  state.indeterminate = false;
  state.columnsTitleList = checked
    ? tableColumns.map(s => `${s.title as string}`)
    : [];
}

/**表格字段列拖拽操作 */
function fnTableColumnsDrop(dropResult: any) {
  const { removedIndex, addedIndex, payload } = dropResult;
  if (removedIndex === null || addedIndex === null) {
    return;
  }
  let itemToAdd = payload;
  itemToAdd = tableColumns.splice(removedIndex, 1)[0];
  tableColumns.splice(addedIndex, 0, itemToAdd);
  fnUpdateColumns();
}

/**表格字段列固定操作 */
function fnTableColumnsFixed(row: Record<string, any>) {
  if (row.fixed === undefined) {
    return;
  }
  const optTitle = t('common.operate');
  if (row.title === optTitle) {
    const optFixed = row.fixed === 'right';
    row.fixed = optFixed ? false : 'right';
  } else {
    row.fixed = !row.fixed;
  }
  fnUpdateColumns();
}

/**表格字段列勾选字段变化 */
function fnUpdateColumns() {
  let list = tableColumns.filter(s =>
    state.columnsTitleList.includes(`${s.title}`)
  );
  // 取消全选时留第一个
  if (list.length === 0) {
    list = [tableColumns[0]];
  }

  if (props.cacheId) {
    // 存入数据
    dbSetJSON(
      CACHE_DB_TABLE_DND,
      `${props.cacheId}#${currentLocale.value}`,
      list
    );
  }
  nextTick(() => {
    emit('update:columns-dnd', list);
  });
}

/**表格字段列勾选监听 */
watch(
  () => state.columnsTitleList,
  val => {
    const len = val.length;
    state.indeterminate = !!len && len < tableColumns.length;
    state.checkAll = len === tableColumns.length;
    fnUpdateColumns();
  }
);

onMounted(() => {
  if (props.cacheId) {
    // 读取数据后响应
    dbGetJSON(CACHE_DB_TABLE_DND, `${props.cacheId}#${currentLocale.value}`)
      .then(data => {
        if (data) {
          const titleList: string[] = [];
          for (const item of data) {
            titleList.push(`${item.title}`);
            // 固定标记还原
            if (item.fixed !== undefined) {
              const fixedItem = tableColumns.find(s => s.title === item.title);
              if (fixedItem) {
                fixedItem.fixed = item.fixed;
              }
            }
          }
          state.columnsTitleList = titleList;
        } else {
          state.columnsTitleList = tableColumns.map(s => `${s.title}`);
        }
      })
      .finally(() => {
        fnUpdateColumns();
      });
  } else {
    state.columnsTitleList = tableColumns.map(s => `${s.title}`);
    fnUpdateColumns();
  }
});
</script>

<template>
  <a-tooltip>
    <template #title>
      {{ t('common.columnSetText') }}
    </template>
    <a-popover trigger="click" placement="bottomRight">
      <template #title>
        <div class="table-column-setting-title">
          <a-checkbox
            v-model:checked="state.checkAll"
            :indeterminate="state.indeterminate"
            @change="fnTableColumnsCheckAllChange"
          >
            {{ t('common.columnSetTitle') }}
          </a-checkbox>
        </div>
      </template>
      <template #content>
        <a-checkbox-group
          v-model:value="state.columnsTitleList"
          style="width: 100%; max-height: 450px; overflow-y: auto"
        >
          <Container orientation="vertical" @drop="fnTableColumnsDrop">
            <Draggable v-for="c in tableColumns" :key="c.title">
              <div class="table-column-setting-list-item">
                <HolderOutlined class="anticon" />
                <a-checkbox :value="c.title">
                  {{ c.title }}
                </a-checkbox>
                <a-button
                  v-if="c.fixed !== undefined"
                  size="small"
                  :title="c.fixed ? `Fixed ${c.fixed} side` : ''"
                  :type="c.fixed ? 'primary' : 'dashed'"
                  @click="fnTableColumnsFixed(c)"
                >
                  <template #icon><FlagOutlined /></template>
                </a-button>
              </div>
            </Draggable>
          </Container>
        </a-checkbox-group>
      </template>
      <a-button :type="props.type" size="small">
        <template #icon><TableOutlined /></template>
        <span v-if="props.type === 'ghost'">
          {{ t('common.columnSetText') }}
        </span>
      </a-button>
    </a-popover>
  </a-tooltip>
</template>

<style lang="less" scoped>
.table-column-setting-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 32px;
  margin-left: 4px;
}

.table-column-setting-list-item {
  display: flex;
  align-items: center;
  width: 100%;
  padding: 4px;
}

.table-column-setting-list-item > .anticon {
  padding-right: 8px;
  cursor: move;
}

.table-column-setting-list-item .ant-checkbox-wrapper {
  flex: 1;
  margin: 0;
}
</style>
