<script setup lang="ts">
import { nextTick, ref, reactive, watch, computed } from 'vue';
import { edtorProps } from '../../model/propsData';

import ErrorIcon from '@/components/ErrorIcon/ErrorIcon.vue';
import ClearableIcon from '@/components/ClearableIcon/ClearableIcon.vue';

import { traduction } from '@/utils/language';
import { getStoreData } from '@/utils/composition';
/* eslint-disable-next-line vue/valid-define-props */
const props: any = defineProps(edtorProps);

const emits = defineEmits([
  'editor',
  'cancel',
  'confirm',
  'clear',
  'change',
  'validate',
  'focus',
  'blur',
  'input'
]);

defineExpose({
  // 清空校验
  clearValidate() {
    formRefObj.value.clearValidate('value');
  },
  // 进行校验
  validate() {
    formRefObj.value.validateField('value');
  },
  // 获取校验结果,不触发表单校验
  getValidateResult() {
    if (props?.rule?.validator) {
      return props.rule.validator(props.rule, editData.value, () => {});
    }
    return true;
  }
});
const language = computed(() => {
  return getStoreData('loct', 'locale');
});
let trigger = 'blur';

const editorIconTip = traduction('COMMON_EDIT');

let editState = ref(false);

// false的时候是清空按钮,true的时候是报错按钮
let suffixIconFlag = ref(false);

// 校验结果
let validateResult = ref(true);

// 是否获取焦点
let focused: boolean = true;

// form的ref对象
const formRefObj = ref();

// 编辑中的数据
let editData = reactive({
  value: props.value
});

let inputRule = reactive({
  value: props.rule
});

const popoverVisible = ref(false);

watch(
  () => props.value,
  (val: string | number) => {
    editData.value = val;
    editState.value = false;
    if (!focused && formRefObj && formRefObj.value) {
      formRefObj.value.validateField('value');
    }
  }
);

watch(
  () => props.rule,
  (val: any) => {
    inputRule.value = val;
    setTrigger();
  }
);

const saveState = computed(() => {
  const { inputType } = props;
  // 传type是数字类型或者没有传type默认是数字类型
  if (inputType === 'number' || !inputType) {
    if (props.value || props.value === 0) {
      return !validateResult.value || Number(props.value) === Number(editData.value);
    } else {
      return true;
    }
  }
  return (
    !validateResult.value ||
    props.value?.toString() === editData.value?.toString() ||
    editData.value === ''
  );
});

// 点击编辑
function selfEditor() {
  if (!props.disabled) {
    emits('editor');
    nextTick(() => {
      editData.value = props.value;
      editState.value = true;
    });
  }
}

// 取消
function back() {
  emits('cancel');
  editState.value = false;
}

// 保存
function save() {
  if (saveState.value) {
    return;
  }

  const { inputType } = props;
  // 传inputType是数字类型或者没有传inputType,默认是数字类型
  if (inputType === 'number' || !inputType) {
    editData.value = Number(editData.value);
    emits('confirm', editData.value);
  }

  emits('confirm', editData.value);
}

// 设置校验方式  是判断输入框的尾部图标的条件之一
function setTrigger() {
  if (props.rule && props.rule.trigger) {
    trigger = props.rule.trigger;
  }
}

setTrigger();

// 清空内容
function clear() {
  input('');
  emits('clear');
  if (!focused) {
    formRefObj.value.validateField('value');
  }
}

// 输入框内容发生修改
function change(value: string) {
  emits('change', value);
}

// 表单校验发生时
function validate(key: string, state: boolean) {
  validateResult.value = state;
  emits('validate', state);
}

// 获取焦点
function focus() {
  formRefObj.value.validateField('value');
  focused = true;
  emits('focus');
  nextTick(() => {
    mouseenter();
  });

  if (props.popoverSetting.show) {
    popoverVisible.value = true;
  }
}

// 失去焦点
function blur() {
  emits('blur');
  focused = false;
  // 因为focus的时候清空了校验,所以如果blur,就要手动触发校验
  if (trigger === 'change') {
    formRefObj.value.validateField('value');
  }
  nextTick(() => {
    mouseleave();
  });

  if (props.popoverSetting.show) {
    popoverVisible.value = false;
  }
}

// 输入框内容发生修改
function input(value: string) {
  emits('input', value);
  nextTick(() => {
    mouseenter();
  });
}

// 鼠标移入
function mouseenter() {
  if (props.clearable) {
    if (trigger === 'blue') {
      if (validateResult.value && editData.value) {
        suffixIconFlag.value = false;
      } else {
        suffixIconFlag.value = true;
      }
    } else {
      if (editData.value) {
        suffixIconFlag.value = false;
      } else {
        suffixIconFlag.value = true;
      }
    }
  }
}

// 鼠标移出
function mouseleave() {
  if (props.clearable) {
    // 获取焦点,且输入框中有内容
    if (focused && editData.value) {
      suffixIconFlag.value = false;
    } else {
      suffixIconFlag.value = true;
    }
  }
}
</script>

<template>
  <div :class="['editor-box', props.disabled ? 'disabled-btn' : '']">
    <!-- 编辑按钮和展示数据 -->
    <div v-if="!editState" class="btn-box" :class="`${language}-language`">
      <span class="value">
        <span :id="props.idStr + 'ShowNum'">{{ props.value }}</span>
        {{ props.unit }}
      </span>

      <el-tooltip
        :content="editorIconTip"
        :teleported="props.teleported"
        placement="top"
        trigger-keys
      >
        <div
          :id="props.idStr"
          :class="['edit-icon', props.disabled ? 'disabled-btn' : '']"
          @click="selfEditor"
        >
          <span class="icon-editor icon" />
        </div>
      </el-tooltip>
    </div>

    <!-- 修改输入框和确认以及取消按钮 -->
    <div v-if="editState" class="edit-content">
      <el-form
        ref="formRefObj"
        class="form"
        :model="editData"
        :rules="inputRule"
        label-width="0px"
        :validate-on-rule-change="false"
        @validate="validate"
      >
        <el-form-item label="" prop="value" class="form-item">
          <!-- 没有popover的输入框 -->
          <el-input
            v-if="!props.popoverSetting.show"
            v-model="editData.value"
            v-addId.input="props.idStr + 'Input'"
            v-clearable="props.clearable"
            :clearable="props.clearable"
            :input-style="props.inputStyle"
            :class="props.classStr"
            :type="props.inputType"
            :placeholder="props.placeholder"
            @mouseenter="mouseenter"
            @mouseleave="mouseleave"
            @clear="clear"
            @input="input"
            @change="change"
            @focus="focus"
            @blur="blur"
          >
            <template v-if="props.clearable" #suffix>
              <ErrorIcon />
              <ClearableIcon />
            </template>
          </el-input>

          <!-- 有popover的输入框 -->
          <el-popover
            v-else
            v-model:visible="popoverVisible"
            :popper-class="props.popoverSetting.popperClass"
            :width="props.popoverSetting.width"
            :placement="props.popoverSetting.placement ? props.popoverSetting.placement : 'right'"
            :trigger="props.popoverSetting.trigger ? props.popoverSetting.trigger : 'focus'"
            trigger-keys
          >
            <!-- 简单的字符串-popover内容 -->
            <span v-if="props.popoverSetting.type === 'ordinary' || !props.popoverSetting.type">
              {{ props.popoverSetting.content }}
            </span>
            <!-- 复杂的自定义展示组件-popover内容 -->
            <component
              :is="props.popoverSetting.popoverSlotSetting.component"
              v-if="
                props.popoverSetting.popoverSlotSetting && props.popoverSetting.type === 'complex'
              "
              :data="props.popoverSetting.popoverSlotSetting.data"
            ></component>
            <template #reference>
              <el-input
                v-model="editData.value"
                v-addId.input="props.idStr + 'Input'"
                v-clearable="props.clearable"
                :clearable="props.clearable"
                :input-style="props.inputStyle"
                :class="props.classStr"
                :type="props.inputType"
                :placeholder="props.placeholder"
                @mouseenter="mouseenter"
                @mouseleave="mouseleave"
                @clear="clear"
                @input="input"
                @change="change"
                @focus="focus"
                @blur="blur"
              >
                <template v-if="props.clearable" #suffix>
                  <ErrorIcon />
                  <ClearableIcon />
                </template>
              </el-input>
            </template>
          </el-popover>
        </el-form-item>
      </el-form>
      <!-- 保存 -->
      <div
        :id="props.idStr + 'Save'"
        class="btn btn-save"
        :class="[saveState ? 'disabled' : '']"
        @click="save"
      >
        {{ $t('COMMON_SAVE') }}
      </div>
      <!-- 取消 -->
      <div :id="props.idStr + 'Cancel'" class="btn" @click="back">
        {{ $t('COMMON_CANCEL') }}
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.editor-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  cursor: pointer;

  .btn-box {
    display: flex;
    align-items: center;
    position: relative;
    width: 60px;
    line-height: 20px;
    &.zh-language {
      width: 85px;
    }
    &.en-language {
      width: 140px;
    }

    .value {
      color: var(--o-text-color-primary);
      font-size: 16px;
      font-weight: 500;

      span {
        white-space: nowrap;
        width: auto;
      }
    }

    .edit-icon {
      margin-top: 3px;
      margin-left: 5px;
      cursor: pointer;

      .icon-editor:before {
        content: '\e906';
        color: var(--o-text-color-tertiary);
      }

      .icon-editor:hover:before {
        color: var(--o-color-primary-secondary);
      }
    }
  }

  .edit-content {
    margin-left: 8px;
    display: flex;
    align-items: center;

    .btn {
      cursor: pointer;
      color: var(--o-color-primary);
    }

    .btn-save {
      margin: 0 8px;
    }

    .disabled {
      cursor: not-allowed;
      color: var(--o-text-color-tertiary);
    }

    :deep(.el-form) {
      .el-form-item {
        margin-bottom: 0px;

        .el-input {
          .el-input__inner {
            line-height: 1px !important;
          }

          .el-input__inner::-webkit-input-placeholder {
            font-size: 12px !important;
          }
        }
      }
    }
  }
}
</style>