<template>
  <div class="input_main">
    <el-input
      ref="tempElInput"
      v-model="inputData"
      :clearable="props.clearable"
      :style="{ width: inputWidth + 'px' }"
      @clear="inputClear"
      @focus="initData"
      @input="inputChange"
      @keydown="keyboardEvent"
    />
    <transition name="el-zoom-in-top">
      <div v-show="inputTable" :style="{ width: props.tableWidth + 'px' }" class="input_box">
        <div class="input_header">
          <span>
            <el-button circle icon="Close" plain type="danger" @click="inputClose"></el-button>
          </span>
          <small>
            <xc-code code="Alt + ↑ / ↓" description="获取行" />
            <xc-code code="Alt + ← / →" description="翻页" />
            <xc-code code="Enter" description="确定" />
          </small>
          <span class="title">
            <strong>
              {{ props.title }}
            </strong>
          </span>
        </div>
        <div class="input_table">
          <el-table
            :data="props.realPagination ? props.data.data : props.data.data.slice((props.data.currentPage - 1) * 10, props.data.currentPage * 10)"
            :height="410"
            :row-class-name="tableRowClassName"
            @row-click="rowClick"
          >
            <el-table-column :width="30" type="index" />
            <template v-for="item in props.tableHeader">
              <el-table-column :label="item.label" :prop="item.prop" :width="item.width" show-overflow-tooltip />
            </template>
          </el-table>
          <el-pagination :current-page="props.data.currentPage" :page-size="10" :total="props.data.total" layout="total,prev, pager, next" @current-change="currentChange" />
        </div>
      </div>
    </transition>
  </div>
</template>

<script name="InputAndTable" setup>
import { stringNotBlank } from '@/utils/blank-utils'
import { debounce } from '@/utils/debounce'

const props = defineProps({
  modelValue: {
    type: String,
    default: '',
  },
  inputWidth: {
    type: Number,
    default: 120,
  },
  tableWidth: {
    type: Number,
    default: 600,
  },
  data: {
    type: Object,
    default: {
      data: [],
      currentPage: 1,
      total: 0,
    },
  },
  tableHeader: {
    type: Array,
  },
  title: {
    type: String,
    default: '数据搜索',
  },
  valueId: {
    type: String,
    default: 'code',
  },
  clearable: {
    type: Boolean,
    default: false,
  },
  realPagination: {
    type: Boolean,
    default: true,
  },
})

const emit = defineEmits(['currentChange', 'rowClick', 'fetchData', 'update:modelValue'])

let inputData = $ref('')
let tempElInput = $ref(null)
let popover = $ref(false)
let inputTable = $ref(false)

const data = ref({
  total: 0,
  currentPage: 1,
  pageSize: 10,
  data: [],
})
// 临时下标用来使用键盘选中的
let tempIndex = $ref(-1)

const inputChange = debounce((value) => {
  if (value.length > 1) {
    emit('fetchData', value)
  }
}, 400)

const initData = () => {
  if (stringNotBlank(props.modelValue) && props.data.total === 0) {
    inputChange(props.modelValue)
  }
  inputTable = true
  // keyboardEvent()
}

const rowClick = (row, column, event) => {
  tempIndex = row.index
  emit('update:modelValue', row[props.valueId])
  inputData = row[props.valueId]
  emit('rowClick', row)
  inputTable = false
}

const currentChange = (val) => {
  tempElInput.focus()
  tempIndex = -1
  if (props.realPagination) {
    emit('currentChange', inputData, val)
  } else {
    props.data.currentPage = val
  }
}

const tableRowClassName = ({ row, rowIndex }) => {
  row.index = rowIndex
  if (props.modelValue === row[props.valueId]) {
    return 'input_and_table_row'
  } else if (rowIndex === tempIndex) {
    return 'input_and_table_to_be_selected'
  }
  return ''
}

const inputClear = () => {
  emit('update:modelValue', '')
  inputData = ''
  emit('rowClick', '')
  tempIndex = -1
}

const inputClose = () => {
  inputTable = false
  tempIndex = -1
  inputData = props.modelValue
}

const enter = () => {
  if (tempIndex < 0 || tempIndex > props.data.data.length) return
  rowClick(props.data.data[tempIndex])
}

const leftOrRight = (val) => {
  let count = Math.ceil(props.data.total / 10)
  let currentPage = props.data.currentPage
  currentPage = val === 'left' ? currentPage - 1 : currentPage + 1
  if (currentPage < 1) {
    currentPage = count
  } else if (currentPage > count) {
    currentPage = 1
  }
  currentChange(currentPage)
}

const upOrLower = (val) => {
  let dataLength = props.data.data.length
  tempIndex = val === 'up' ? tempIndex - 1 : tempIndex + 1
  if (tempIndex < 0) {
    tempIndex = dataLength - 1
  } else if (tempIndex >= dataLength) {
    tempIndex = 0
  }
}

const keyboardEvent = (event) => {
  if (event.key === 'Escape') {
    event.returnValue = false
    inputClose()
  }
  if (props.data.total > 0) {
    if (event.altKey && event.keyCode === 37) {
      event.returnValue = false
      leftOrRight('left')
    } else if (event.altKey && event.keyCode === 38) {
      event.returnValue = false
      upOrLower('up')
    } else if (event.altKey && event.keyCode === 39) {
      event.returnValue = false
      leftOrRight('right')
    } else if (event.altKey && event.keyCode === 40) {
      event.returnValue = false
      upOrLower('lower')
    } else if (event.keyCode === 13) {
      enter()
    }
  }
}

const focus = () => {
  tempElInput.focus()
}

watch(
  () => props.modelValue,
  () => {
    inputData = props.modelValue
  }
)

onMounted(() => {
  inputData = props.modelValue
})

defineExpose({ focus })
</script>

<style>
.el-table .input_and_table_row {
  background: rgba(71, 123, 220, 0.69);
}

.el-table .input_and_table_to_be_selected {
  background: #f8cc48a1;
}
</style>

<style lang="scss" scoped>
.input_main {
  position: relative;
  display: inline-block;

  .input_box {
    box-shadow: 0 0 12px rgba(0, 0, 0, 0.12);
    border-radius: 5px;
    display: flex;
    position: absolute;
    flex-direction: column;
    z-index: 1000;
    top: 28px;
    background-color: white;

    .input_header {
      height: 40px;
      border-radius: 5px;
      line-height: 40px;
      display: flex;
      justify-content: space-between;
      padding: 5px;
      background-color: #f8f8f8;

      .title {
        font-size: 20px;
        text-align: center;
      }
    }
  }
}
</style>
