<template>
  <div class="editable-cell">
    <!-- 显示模式  -->
    <div class="editable-cell-text-wrapper" v-if="!getRowValue && !editable">
      <div> {{ value }}</div>
      <div class="editable-cell-action">
        <edit-outlined class="editable-cell-icon" @click="editCell" />
      </div>
    </div>
    <!-- 编辑模式 -->
    <a-popover
      v-else
      :destroyTooltipOnHide="true"
      :visible="!isUndefined(getValidateInfo) && visible"
      :content="getValidateInfo?.message"
      :overlayClassName="'ns-cell-rule-popover'"
      :getPopupContainer="(triggerNode) => triggerNode.parentNode"
    >
      <div class="editable-cell-input-wrapper">
        <component :is="column.edit.component || 'NsInput'" v-bind="formProps" />
        <!--单元格编辑-->
        <div class="editable-cell-action" v-if="editable">
          <check-outlined class="editable-cell-icon" @click="saveCell" />
          <!-- <close-outlined class="editable-cell-icon" @click="cancelCell" /> -->
        </div>
      </div>
    </a-popover>
  </div>
</template>
<script lang="ts">
  import { computed, defineComponent, inject, nextTick, PropType, ref, watch } from 'vue';
  import { PropTypes } from '/nerv-lib/util/type';
  import { CheckOutlined, CloseOutlined, EditOutlined } from '@ant-design/icons-vue';
  import { TableEdit } from '/nerv-lib/component/table/use-table-edit';
  import { isUndefined, upperFirst } from 'lodash-es';
  import Schema from 'async-validator';

  export default defineComponent({
    name: 'NsTableCell',
    components: {
      EditOutlined,
      CheckOutlined,
      CloseOutlined,
    },
    props: {
      value: {
        type: [String, Number, Boolean, Object] as PropType<string | number | boolean | Recordable>,
        default: '',
        required: true,
      },
      record: {
        type: Object as PropType<Recordable>,
        required: true,
      },
      column: {
        type: Object as PropType<Recordable>,
        required: true,
        default: () => ({}),
      },
      index: PropTypes.number,
    },
    setup(props) {
      const {
        getValidate,
        setValidate,
        setValue,
        getValue,
        getKey,
        validate,
        tableEdit,
        tableSave,
      } = inject('tableEdit') as TableEdit;
      const visible = ref(true);

      const getRowKey = computed(() => {
        return getKey({ ...props.record });
      });

      const getField = computed(() => {
        return props.column.dataIndex;
      });

      let editable = ref(false);

      const getCellValue = computed({
        get: () => getValue(getRowKey.value, getField.value),
        set: (val) => setValue(getRowKey.value, val, getField.value),
      });

      watch(
        () => props.index,
        () => {
          console.log('index', props.record, props.index);
        },
        {
          deep: true,
        }
      );

      const getRowValue = computed(() => {
        return getValue(getRowKey.value);
      });

      const getValidateInfo = computed({
        get: () => getValidate(getRowKey.value, getField.value),
        set: (val) => setValidate(getRowKey.value, val, getField.value),
      });

      // setTimeout(() => console.log('getCellValue', getCellValue.value), 1000);

      watch(
        [() => getCellValue.value, () => getRowValue.value],
        () => {
          validate(getRowKey.value, getField.value);
        },
        {
          immediate: true,
        }
      );

      /**
       * 解决删除后验证遗留的问题
       */
      watch(
        () => props.index,
        () => {
          if (getValidateInfo.value) {
            visible.value = false;
            // 延迟等待隐藏动画操作
            setTimeout(() => {
              visible.value = true;
            });
          }
        }
      );

      const editCell = () => {
        tableEdit(getRowKey.value, getField.value);
        editable.value = true;
      };

      const cancelCell = () => {
        getValidateInfo.value = undefined; //清空验证信息
        editable.value = false;
      };

      const saveCell = () => {
        // console.log('getValidated.value', getValidated.value);
        if (!getValidateInfo.value) {
          editable.value = false;
          tableSave(getRowKey.value, getField.value);
        }
      };

      const formProps = computed(() => {
        const {
          component,
          valueField,
          changeEvent = 'change',
          props: componentProps,
        } = props.column.edit;

        const isCheck =
          component && ['NsSwitch', 'NsCheckbox', 'Switch', 'Checkbox'].includes(component);
        const bindValue: Recordable = {
          [valueField || (isCheck ? 'checked' : 'value')]: getCellValue.value,
        };
        const eventKey = `on${upperFirst(changeEvent)}`;

        const on = {
          [eventKey]: (...args: Nullable<Recordable>[]) => {
            const [e] = args;
            const target = e ? e.target : null;
            getCellValue.value = target ? (isCheck ? target.checked : target.value) : e;
          },
        };
        return {
          ...componentProps,
          ...bindValue,
          ...on,
        };
      });

      return {
        editCell,
        saveCell,
        cancelCell,
        editable,
        formProps,
        visible,
        getValidateInfo,
        getCellValue,
        getRowValue,
        isUndefined,
      };
    },
  });
</script>
<style lang="less" scoped>
  .ns-cell-rule-popover {
    color: @error-color;
  }

  .editable-cell {
    position: relative;

    .editable-cell-input-wrapper,
    .editable-cell-text-wrapper {
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .editable-cell-action {
      width: 36px;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .editable-cell-icon {
      width: 24px;
      line-height: 28px;
      opacity: 0;
    }

    &:hover .editable-cell-icon {
      color: #108ee9;
      opacity: 1;
    }

    .editable-add-btn {
      margin-bottom: 8px;
    }
  }

  .editable-cell:hover .editable-cell-icon {
    display: inline-block;
  }
  :deep(.ant-popover) {
    z-index: 50;
  }
</style>