<template>
  <table-box
    ref="table"
    style="height: 100%"
    :data="dataList"
    :key="tableKey"
    show-overflow="title"
    show-header-overflow="title"
    class="draggable-widget page-table"
    header-cell-class-name="table-header-gray"
    :hasImageColumn="hasImageColumn"
    :size="layoutStore.defaultFormItemSize"
    :keep-source="rowEdit"
    :tree-config="treeConfig"
    :edit-config="{
      trigger: 'manual',
      mode: 'row',
      enabled: rowEdit,
      showIcon: false,
      autoClear: false,
      showStatus: true,
    }"
    :edit-closed="onSaveRowData"
    :seq-config="{ seqMethod }"
    :hasExtend="hasExtend"
    @sort-change="onSortChange"
    @checkbox-select-change="onCheckBoxChange"
    @radio-select-change="onRadioSelectChange"
    :sort-config="{ remote: remoteSort }"
    @refresh="onRefresh"
  >
    <template
      v-slot:operator
      v-if="
        operationList.filter(row => {
          return row.enabled && !row.rowOperation;
        }).length > 0 && !form().readOnly
      "
    >
      <el-button
        class="table-operation"
        v-if="operationVisible(SysCustomWidgetOperationType.BATCH_DELETE)"
        :size="layoutStore.defaultFormItemSize"
        :type="getOperation(SysCustomWidgetOperationType.BATCH_DELETE).btnType"
        :plain="getOperation(SysCustomWidgetOperationType.BATCH_DELETE).plain"
        :disabled="operationDisabled(SysCustomWidgetOperationType.BATCH_DELETE)"
        @click="onOperationClick(getOperation(SysCustomWidgetOperationType.BATCH_DELETE))"
        :icon="Delete"
        >{{ getOperation(SysCustomWidgetOperationType.BATCH_DELETE).name || '批量删除' }}</el-button
      >
      <el-button
        class="table-operation"
        v-if="operationVisible(SysCustomWidgetOperationType.EXPORT)"
        :size="layoutStore.defaultFormItemSize"
        :type="getOperation(SysCustomWidgetOperationType.EXPORT).btnType"
        :plain="getOperation(SysCustomWidgetOperationType.EXPORT).plain"
        :disabled="operationDisabled(SysCustomWidgetOperationType.EXPORT)"
        @click="onOperationClick(getOperation(SysCustomWidgetOperationType.EXPORT))"
        :icon="Download"
        >{{ getOperation(SysCustomWidgetOperationType.EXPORT).name || '导出' }}</el-button
      >
      <el-upload
        v-if="operationVisible(SysCustomWidgetOperationType.IMPORT)"
        action=""
        accept=".xlsx, .xls"
        :before-upload="onImportClick"
      >
        <el-button
          :size="layoutStore.defaultFormItemSize"
          :type="getOperation(SysCustomWidgetOperationType.IMPORT).btnType"
          :plain="getOperation(SysCustomWidgetOperationType.IMPORT).plain"
          :disabled="operationDisabled(SysCustomWidgetOperationType.IMPORT)"
          icon="el-icon-upload2"
          >{{ getOperation(SysCustomWidgetOperationType.IMPORT).name || '导入' }}</el-button
        >
      </el-upload>
      <el-button
        class="table-operation"
        v-if="
          operationVisible(SysCustomWidgetOperationType.PRINT) &&
          getOperation(SysCustomWidgetOperationType.PRINT).rowOperation
        "
        :size="layoutStore.defaultFormItemSize"
        :type="getOperation(SysCustomWidgetOperationType.PRINT).btnType"
        :plain="getOperation(SysCustomWidgetOperationType.PRINT).plain"
        :disabled="operationDisabled(SysCustomWidgetOperationType.PRINT)"
        @click="onOperationClick(getOperation(SysCustomWidgetOperationType.PRINT))"
        >{{ getOperation(SysCustomWidgetOperationType.PRINT).name || '打印' }}</el-button
      >
      <el-button
        class="table-operation"
        v-if="operationVisible(SysCustomWidgetOperationType.ADD)"
        :size="layoutStore.defaultFormItemSize"
        :type="getOperation(SysCustomWidgetOperationType.ADD).btnType"
        :plain="getOperation(SysCustomWidgetOperationType.ADD).plain"
        :disabled="operationDisabled(SysCustomWidgetOperationType.ADD)"
        @click="onOperationClick(getOperation(SysCustomWidgetOperationType.ADD))"
        :icon="Plus"
        >{{ getOperation(SysCustomWidgetOperationType.ADD).name || '新建' }}</el-button
      >
    </template>
    <vxe-column v-if="hasBatchOperation && !form().readOnly" type="checkbox" :width="40" />
    <vxe-column v-if="singleSelect" type="radio" align="center" :width="50" />
    <vxe-column
      v-if="tableColumnList.length > 0"
      type="seq"
      title="序号"
      :width="treeConfig != null ? 90 : 50"
      :tree-node="treeConfig != null"
    />
    <template v-for="tableColumn in tableColumnList" :key="tableColumn.column?.columnId">
      <!-- Boolean类型字段 -->
      <vxe-column
        v-if="tableColumn.column && tableColumn.column.objectFieldType === 'Boolean'"
        :title="tableColumn.showName"
        :width="tableColumn.columnWidth"
      >
        <template #default="{ row }">
          <el-tag
            :size="layoutStore.defaultFormItemSize"
            :type="getObjectValue(row, tableColumn.showFieldName) ? 'success' : 'danger'"
          >
            {{ getObjectValue(row, tableColumn.showFieldName) ? '是' : '否' }}
          </el-tag>
        </template>
      </vxe-column>
      <!-- 图片类型字段 -->
      <vxe-column
        v-else-if="
          tableColumn.column && tableColumn.column.fieldKind === SysOnlineFieldKind.UPLOAD_IMAGE
        "
        :title="tableColumn.showName"
        :width="tableColumn.columnWidth"
      >
        <template #default="{ row }">
          <el-image
            v-for="item in parseTableUploadData(tableColumn, row)"
            :preview-src-list="getTablePictureList(tableColumn, row)"
            class="table-cell-image"
            :key="item.url"
            :src="item.url"
            fit="fill"
          >
            <template v-slot:error>
              <div class="table-cell-image">
                <el-icon><Picture /></el-icon>
              </div>
            </template>
          </el-image>
        </template>
      </vxe-column>
      <!-- 文件下载类型字段 -->
      <vxe-column
        v-else-if="tableColumn.column && tableColumn.column.fieldKind === SysOnlineFieldKind.UPLOAD"
        :title="tableColumn.showName"
        :width="tableColumn.columnWidth"
      >
        <template #default="{ row }">
          <a
            v-for="item in parseTableUploadData(tableColumn, row)"
            :key="item.url"
            href="javascript:void(0);"
            @click="downloadFile(item.url, item.name)"
          >
            {{ item.name }}
          </a>
        </template>
      </vxe-column>
      <!-- 其他类型 -->
      <vxe-column
        v-else
        :title="tableColumn.showName"
        :field="tableColumn.showFieldName"
        :width="tableColumn.columnWidth"
        :sortable="tableColumn.sortable"
      />
    </template>
    <vxe-column
      title="操作"
      :width="widget.props.operationColumnWidth || 160"
      fixed="right"
      :show-overflow="false"
      v-if="(rowEdit || tableOperationList.length > 0) && tableColumnList.length > 0"
    >
      <template #default="{ row }">
        <el-button
          v-for="operation in tableOperationList"
          :key="operation.id"
          v-show="form().checkOperationVisible(operation, row)"
          :size="layoutStore.defaultFormItemSize"
          link
          :class="operation.btnClass"
          :disabled="
            !form().checkOperationPermCode(operation) ||
            form().checkOperationDisabled(operation, row)
          "
          @click="onOperationClick(operation, row)"
        >
          {{ operation.name }}
        </el-button>
      </template>
    </vxe-column>
    <template v-slot:empty>
      <div class="table-empty unified-font">
        <img src="@/assets/img/empty.png" />
        <span>暂无数据</span>
      </div>
    </template>
    <template v-slot:pagination>
      <slot name="pagination" />
    </template>
  </table-box>
</template>

<script setup lang="ts">
import { VxeColumn } from 'vxe-table';
import { Picture, Delete, Download, Plus } from '@element-plus/icons-vue';
import TableBox from '@/components/TableBox/index.vue';
import { useDownload } from '@/common/hooks/useDownload';
import { ANY_OBJECT } from '@/types/generic';
import { findItemFromList, getObjectValue } from '@/common/utils';
import { SysCustomWidgetOperationType } from '@/common/staticDict';
import { SysOnlineFieldKind } from '@/common/staticDict/online';
import { useUpload } from '@/common/hooks/useUpload';
import { SortInfo } from '@/common/types/sortinfo';
import { API_CONTEXT } from '@/api/config';
import { useLayoutStore } from '@/store';

const layoutStore = useLayoutStore();
const { downloadFile } = useDownload();
const { parseUploadData } = useUpload();

const emit = defineEmits<{
  delete: [ANY_OBJECT];
  operationClick: [ANY_OBJECT, ANY_OBJECT | null];
  refresh: [];
}>();
const props = withDefaults(
  defineProps<{
    dataList?: Array<ANY_OBJECT>;
    height?: string | number;
    border?: string;
    // 是否支持行内编辑
    rowEdit?: boolean;
    // 是否支持多选
    multiSelect?: boolean;
    // 是否支持单选
    singleSelect?: boolean;
    // 表格操作列表
    operationList?: Array<ANY_OBJECT>;
    widget: ANY_OBJECT;
    // 获取行序号
    getTableIndex?: (value: number) => number;
    // 排序改变
    sortChange?: (value: SortInfo) => void;
    // 多选选中改变
    onSelectChange?: (values: Array<ANY_OBJECT>) => void;
    // 单选中改变
    onRadioChange?: (value: ANY_OBJECT) => void;
    treeConfig?: ANY_OBJECT;
  }>(),
  {
    dataList: () => [],
    height: 'auto',
    border: 'full',
    rowEdit: false,
    multiSelect: false,
    singleSelect: false,
    operationList: () => [],
    treeConfig: undefined,
  },
);

const table = ref();
const form = inject('form', () => {
  console.error('OnlineCustomTable: form not injected');
  return { isEdit: false } as ANY_OBJECT;
});

const slots = useSlots();

// const editInfo = reactive<ANY_OBJECT>({
//   editRow: undefined,
// });
const sortInfo = ref<SortInfo | null>(null);

const buildFlowParam = computed(() => {
  let flowParam: ANY_OBJECT = {};
  let flowData = form().flowData;
  if (flowData) {
    if (flowData.processDefinitionKey)
      flowParam.processDefinitionKey = flowData.processDefinitionKey;
    if (flowData.processInstanceId) flowParam.processInstanceId = flowData.processInstanceId;
    if (flowData.taskId) flowParam.taskId = flowData.taskId;
  }

  return flowParam;
});
const tableColumnList = computed(() => {
  let tempList =
    props.widget && props.widget.props && Array.isArray(props.widget.props.tableColumnList)
      ? props.widget.props.tableColumnList
      : [];
  const res: ANY_OBJECT[] = [];
  for (const tempItem of tempList) {
    const item = { ...tempItem };
    if (item.fieldType === 0 || item.fieldType == null) {
      // 绑定表字段
      if (item.column) item.showFieldName = item.column.columnName;
      if (props.widget.relation == null && item.relation != null) {
        item.showFieldName = item.relation.variableName + '.' + item.showFieldName;
      }
      if (item.column && item.column.dictInfo) {
        item.showFieldName = item.showFieldName + 'DictMap.name';
      }
    } else {
      // 自定义字段
      item.showFieldName = item.customFieldName;
    }
    res.push(item);
  }
  return res;
});
const tableOperationList = computed(() => {
  return props.operationList.filter(item => {
    let temp = item.enabled && item.rowOperation;
    if (temp && form().readOnly) {
      temp = temp && item.readOnly;
    }
    return temp;
  });
});
const hasBatchOperation = computed(() => {
  let batchDeleteOperation = findItemFromList(
    props.operationList,
    SysCustomWidgetOperationType.BATCH_DELETE,
    'type',
  );
  let printOperation = findItemFromList(
    props.operationList,
    SysCustomWidgetOperationType.PRINT,
    'type',
  );
  return (
    (batchDeleteOperation != null && batchDeleteOperation.enabled) ||
    (printOperation != null && printOperation.enabled && !printOperation.rowOperation)
  );
});
const hasImageColumn = computed(() => {
  return (
    tableColumnList.value.filter((tableColumn: ANY_OBJECT) => {
      return tableColumn.column && tableColumn.column.fieldKind === SysOnlineFieldKind.UPLOAD_IMAGE;
    }).length > 0
  );
});
const tableKey = computed(() => {
  return (props.widget || {}).variableName + new Date().getTime() + tableColumnList.value.length;
});
const remoteSort = computed(() => {
  return props.widget ? (props.widget.props || {}).paged : false;
});
const hasExtend = computed(() => {
  return (
    (props.operationList.filter(row => {
      return row.enabled && !row.rowOperation;
    }).length > 0 &&
      !form().readOnly) ||
    (slots.operator && slots.operator()) != null
  );
});

const onRefresh = () => {
  emit('refresh');
};
const hasOperator = (type: string) => {
  let temp = getOperation(type);
  return temp && temp.enabled;
};
const getOperation = (type: string) => {
  return findItemFromList(props.operationList, type, 'type') || {};
};
const operationVisible = (type: string) => {
  let operation = getOperation(type);
  if (!operation) return false;
  return !form().readOnly && hasOperator(type) && form().checkOperationVisible(operation);
};
const operationDisabled = (type: string) => {
  let operation = getOperation(type);
  return form().checkOperationDisabled(operation) || !form().checkOperationPermCode(operation);
};
const seqMethod = (data: ANY_OBJECT) => {
  if (props.getTableIndex) {
    return props.getTableIndex(data.seq - 1);
  } else {
    return data.seq;
  }
};
const onSortChange = (data: ANY_OBJECT) => {
  if (!props.widget.props.paged) return;
  let fieldName = data.property.replace('DictMap.name', '');
  let order = data.order;
  if (order == null) {
    fieldName = undefined;
  }
  if (order === 'asc') order = 'ascending';
  if (
    sortInfo.value != null &&
    sortInfo.value?.prop === fieldName &&
    sortInfo.value?.order === order
  ) {
    return;
  }
  sortInfo.value = {
    prop: fieldName,
    order: order,
  };
  if (props.sortChange) {
    props.sortChange(sortInfo.value);
  }
};
const onCheckBoxChange = () => {
  if (table.value && typeof props.onSelectChange === 'function') {
    let selectRows = table.value.getTableImpl().getCheckboxRecords(true);
    props.onSelectChange(selectRows);
  }
};
const onRadioSelectChange = () => {
  if (table.value && typeof props.onRadioChange === 'function') {
    let selectRow = table.value.getTableImpl().getRadioRecord();
    props.onRadioChange(selectRow);
  }
};
const setSelectedRow = (rowNum: number) => {
  nextTick(() => {
    table.value.getTableImpl().setRadioRow(props.dataList[rowNum]);
    onRadioSelectChange();
  });
};
// 取消行内编辑
// const cancelRowEvent = (row: ANY_OBJECT) => {
//   if (form().isEdit) return;
//   table.value
//     .getTableImpl()
//     .clearActived()
//     .then(() => {
//       // 还原行数据
//       table.value.getTableImpl().revertData(row);
//       editInfo.editRow = undefined;
//     })
//     .catch(e => {
//       console.warn(e);
//     });
// };
// 启动行内编辑
// const editRowEvent = (row: ANY_OBJECT) => {
//   if (form().isEdit) return;
//   table.value.getTableImpl().setEditRow(row);
//   editInfo.editRow = row;
// };
// 保存行内编辑数据
// const saveRowEvent = (row: ANY_OBJECT) => {
//   if (form().isEdit) return;
//   table.value
//     .getTableImpl()
//     .clearActived()
//     .then(() => {
//       table.value.getTableImpl().reloadRow(row);
//       editInfo.editRow = undefined;
//     });
// };
const onSaveRowData = ({ row }: { row: ANY_OBJECT }) => {
  console.log(row);
};
// 新建行内编辑数据
// const addRowEvent = (row: ANY_OBJECT) => {
//   if (form().isEdit) return;
//   table.value
//     .getTableImpl()
//     .insertAt(row, 0)
//     .then((res: ANY_OBJECT) => {
//       let newRow = res.row;
//       table.value.getTableImpl().setEditRow(newRow);
//     });
// };
// 删除行数据
// const deleteRowEvent = (row: ANY_OBJECT) => {
//   if (form().isEdit) return;
//   emit('delete', row);
// };
const onImportClick = (file: ANY_OBJECT) => {
  onOperationClick(getOperation(SysCustomWidgetOperationType.IMPORT), file);
  return false;
};
const onOperationClick = (operation: ANY_OBJECT, row: ANY_OBJECT | null = null) => {
  emit('operationClick', operation, row);
};
const refreshColumn = () => {
  nextTick(() => {
    if (table.value) table.value.getTableImpl().refreshColumn();
  });
};
const getDownloadUrl = (tableColumn: ANY_OBJECT) => {
  let downloadUrl = null;
  if (form().flowData != null) {
    downloadUrl = API_CONTEXT + '/flow/flowOnlineOperation/download';
  } else {
    if (tableColumn.relationId) {
      downloadUrl =
        API_CONTEXT +
        '/online/onlineOperation/downloadOneToManyRelation/' +
        (props.widget.datasource || {}).variableName;
    } else {
      downloadUrl =
        API_CONTEXT +
        '/online/onlineOperation/downloadDatasource/' +
        (props.widget.datasource || {}).variableName;
    }
  }

  return downloadUrl;
};
const parseTableUploadData = (tableColumn: ANY_OBJECT, row: ANY_OBJECT) => {
  let jsonData = getObjectValue(row, tableColumn.showFieldName);
  console.log('parseTableUploadData', tableColumn, row, jsonData);
  if (!jsonData) return [];
  let downloadParams: ANY_OBJECT = {
    ...buildFlowParam.value,
    datasourceId: props.widget.datasource.datasourceId,
    relationId: tableColumn.relationId,
    fieldName: tableColumn.column?.columnName,
    asImage: tableColumn.column?.fieldKind === SysOnlineFieldKind.UPLOAD_IMAGE,
  };

  if (props.widget.primaryColumnName != null) {
    downloadParams.dataId = row[props.widget.primaryColumnName] || '';
  }

  let downloadUrl = getDownloadUrl(tableColumn);

  console.log('parseTableUploadData downloadUrl', downloadUrl);
  console.log('parseTableUploadData jsonData.toString()', jsonData.toString());
  let temp = JSON.parse(jsonData.toString());
  temp = Array.isArray(temp)
    ? temp.map(item => {
        return {
          ...item,
          downloadUri: downloadUrl,
        };
      })
    : [];
  return parseUploadData(JSON.stringify(temp), downloadParams);
};
const getTablePictureList = (tableColumn: ANY_OBJECT, row: ANY_OBJECT) => {
  let temp = parseTableUploadData(tableColumn, row);
  if (Array.isArray(temp)) {
    return temp.map(item => item.url);
  }
};
const formatListData = (data: ANY_OBJECT) => {
  if (data == null) return;
  Object.keys(data).forEach(key => {
    let subData = data[key];
    if (typeof subData === 'object' && key.indexOf('DictMap') === -1) {
      formatListData(subData);
    } else {
      // 如果是多选字典字段，那么把选中的字典值拼接成DictMap去显示
      if (key.indexOf('DictMapList') !== -1 && Array.isArray(data[key])) {
        let newKey = key.replace('DictMapList', 'DictMap');
        data[newKey] = {
          id: data[key.replace('DictMapList', '')],
          name: data[key].map((subItem: ANY_OBJECT) => subItem.name).join(','),
        };
      }
    }
  });
};

watch(
  () => props.dataList,
  () => {
    if (Array.isArray(props.dataList)) {
      props.dataList.forEach(item => {
        formatListData(item);
      });
      //console.log('OnlineCumstomTable.dataList', props.dataList);
    }
  },
  {
    immediate: true,
  },
);
watch(
  () => tableColumnList.value,
  () => {
    refreshColumn();
  },
  {
    immediate: true,
  },
);
watch(
  () => props.widget.props.operationColumnWidth,
  () => {
    refreshColumn();
  },
);

defineExpose({
  setSelectedRow,
});
</script>

<style scoped>
.table-operation {
  display: inline-block;
}
.table-operation + .table-operation {
  margin-left: 8px;
}
</style>
