<template>
  <td v-if="showSelection == true" class="ant-table-cell ant-table-cell-fix-left ant-table-selection-column"
    :style="{ height: '26px', borderBottom: '1px solid #f0f0f0', borderRight: '1px solid #f0f0f0', position: 'sticky', left: '0px', 'z-index': 3, background: '#fff', padding: '0px!important' }">
  </td>
  <td v-if="showIndex == true" class="ant-table-cell ant-table-cell-fix-left"
    :style="{ height: '26px', borderBottom: '1px solid #f0f0f0', borderRight: '1px solid #f0f0f0', textAlign: 'center', position: 'sticky', left: showSelection == true ? '50px' : '0px', 'z-index': 3, background: '#fff', padding: '0px!important' }">
    <ReloadOutlined @click="cleanFilter" />
  </td>
  <td @keydown.enter="_onEnter" v-for="(item, index)  in props.columns" :class="getClassName(index)" :key="index" :style="{
    height: '26px', borderBottom: '1px solid #f0f0f0', borderRight: '1px solid #f0f0f0', position: tdPosition(index), left: tdLeft(index, item),
    'z-index': tdZindex(index), background: '#fff', right: tdRight(index, item), padding: '0px!important'
  }">
    <Input style="width: 100%;" v-if="_isTextBox(item.dataIndex)" @blur="_onTextBlur" @keyup.enter="_onTextBlur"
      @change="_onTextChange" v-model:value="columnFilterValue[item.dataIndex as string]" size="small"></Input>
    <Select firstActiveValue allowClear size="small" style="width: 100%;" @change="_onSelectChange"
      :mode="getSelectMode(item)" v-if="_isCombox(item.dataIndex)"
      v-model:value="columnFilterValue[item.dataIndex as string]" placeholder :options="getOption(item)">
    </Select>
    <Select firstActiveValue allowClear size="small" style="width: 100%;" @change="_onSelectChange"
      v-if="_isCheckbox(item.dataIndex)" v-model:value="columnFilterValue[item.dataIndex as string]" placeholder
      :options="getCheckOption()">
    </Select>
    <Select firstActiveValue allowClear size="small" style="width: 100%;" @change="_onSelectChange"
      v-if="_isTree(item.dataIndex)" v-model:value="columnFilterValue[item.dataIndex as string]"
      :field-names="{ label: 'name', value: 'id', options: 'children' }" placeholder :mode="getSelectMode(item)"
      :options="getOption(item)">
    </Select>
    <DatePicker size="small" v-if="_isDataTime(item.dataIndex)"
      v-model:value="columnFilterValue[item.dataIndex as string]" allowClear mode="date" style="width: 100%"
      @change="_getDateString()" format="YYYY-MM-DD" valueFormat="YYYY-MM-DD">
    </DatePicker>
    <!-- </template> -->
  </td>
  <!-- <td
v-if="showEditInDialog == true" class="ant-table-cell ant-table-cell-fix-left ant-table-selection-column"
    :style="{ width: '60px', height: '26px', borderBottom: '1px solid #f0f0f0', borderRight: '1px solid #f0f0f0', position: 'sticky', right: ifContainScrollY() ? '17px' : '0px', 'z-index': 3, background: '#fff', padding: '0px!important', }">
  </td> -->
</template>
<script lang="tsx" setup name="ColFilter" :inheritAttrs=false>
import type{  cloumnFilterItem } from "../dynamic-table"
import { onBeforeMount, onMounted, reactive, ref, watchEffect, computed, nextTick, onUnmounted, onUpdated } from "vue"
import { Input, Select, DatePicker } from "ant-design-vue";
import {
  ReloadOutlined
} from '@ant-design/icons-vue';
import type { orderParamaItem, tdStyle } from "../types/"
import type {
  TableColumn,
} from '../types/';
import { i18n } from "../../../../locales/index"

const props = defineProps({
  columns: {
    type: Array as PropType<TableColumn<any>[]>,
    default() {
      return [];
    },
  },
  columnFilter: {
    type: Array as PropType<cloumnFilterItem[] | string[]>,
    default() {
      return [];
    },
  },
  fixed: {
    type: Boolean,
    default: false
  },
  externalQueryParama: Object,
  orderParam: {
    type: Array as PropType<orderParamaItem[]>,
    default() {
      return [];
    },
  },
  isUnion: {
    type: Boolean,
    default: false
  },
  tableID: {
    type: String,
  },
  showIndex: {
    type: Boolean,
    default: true
  },
  rowSelection: {
    type: Object
  },
  mainParmas: {
    //模糊查询参数
    type: Object
  },
  mainStyle: {
    type: Array as PropType<tdStyle[]>,
  },
  showEditInDialog: {
    type: Boolean,
    default: true
  }
})


let columnFilterValue = reactive({}) //保存列筛选用户输入的值
let hasfilterValueChange = ref(false)//表示筛选中的输入框类型的条件已经被改变，因为不能以改变就触发table的重新加载事件，而是等输入框失去焦点才触发。
let isCleanFilterChange = ref(false) //表示筛选条件是有清空筛选条件触发的，这时候并不需要通知触发columnFilter事件，而是触发cleanFilter事件
const emit = defineEmits(['ColFilterChange', 'ColumnFilter', 'CleanFilter']);

const getOption = function (data) {
  for (let i in props.columnFilter) {
    var filter = props.columnFilter[i];
    if (typeof filter == 'object') {
      if (filter.prop == data.dataIndex) {
        return filter.options
      }
    }
  }
  return []
}

const getSelectMode = function (item) {
  enum modeOption {
    multiple = "multiple",
    tags = "tags",
    combobox = "combobox",
    SECRET_COMBOBOX_MODE_DO_NOT_USE = "SECRET_COMBOBOX_MODE_DO_NOT_USE",
  }

  let mode = modeOption.combobox
  for (let i in props.columnFilter) {
    var filter = props.columnFilter[i];
    if (typeof filter == 'object') {
      if (filter.prop == item.dataIndex) {

        if (filter.mode) {
          if ((Object.values(modeOption) as string[]).includes(filter.mode))
            mode = modeOption[filter.mode]
          break
        }

      }
    }
  }

  return mode || undefined
}

const tdPosition = function (index: number) {
  let style = {} as any
  let actIndex = getIndex()
  if (props.mainStyle?.length) {
    style = props.mainStyle[actIndex + index].position
  }
  return style
}

const getClassName = function (index: number) {
  let className = ""
  let actIndex = getIndex()

  if (props.mainStyle?.length) {
    className = props.mainStyle[actIndex + index].class
  }
  return className
}

const tdLeft = function (index: number, item: TableColumn) {
  let style = ""
  let actIndex = getIndex()
  if (props.mainStyle?.length) {
    style = props.mainStyle[actIndex + index].left
  }
  //因为第一次进来的时候，前端获取不到表头的相对位置信息，因此第一次需要自己计算
  if (item.fixed == true || item.fixed == 'left') {
    if (style == "0px" || style == "" || typeof style == "undefined") {
      return getLeft(item)
    } else {
      return style
    }
  } else {
    return style
  }


}

const tdZindex = function (index: number) {
  let style = {} as any
  let actIndex = getIndex()
  if (props.mainStyle?.length) {
    style = props.mainStyle[actIndex + index].zIndex
  }
  return style
}

const tdRight = function (index: number, item: TableColumn) {
  let style = ""
  let actIndex = getIndex()
  if (props.mainStyle?.length) {
    style = props.mainStyle[actIndex + index].right
  }
  if (item.fixed == 'right') {
    if (index < props.columns.length - 1) {
      //说明不是最后一个
      if (style == '0px' || style == "" || typeof style == "undefined") {
        return getRight(item)
      } else {
        return style
      }
    } else {
      //如果是最后一个的话
      if (ifContainScrollY()) {
        //有滚定调，则预留滚动条的宽度
        return "17px"
      } else {
        return '0px'
      }
    }
  }
  else {
    return style
  }
}

const getIndex = function () {
  if (props.rowSelection && props.showIndex) {
    return 2
  } else if (!props.rowSelection && !props.showIndex) {
    return 0
  } else {
    return 1
  }

}
const getCheckOption = function () {
  const { t } = i18n.global
  return [
    {
      value: null,
      label: t("component.table.allLabel"),
    },
    {
      value: true,
      label: t("component.table.YesLabel"),
    },
    {
      value: false,
      label: t("component.table.NoLabel"),
    },
  ]
}

const _isDataTime = function (prop) {
  //判断模糊查询里面，是不是日期控件
  for (var i in props.columnFilter) {
    var filter = props.columnFilter[i];
    if (typeof filter == "object") {
      if (filter.prop && filter.prop == prop) {
        //设置有prop时以prop判断，没有设置，仅仅设置了空属性时，如columnFilter[i]=prop
        if (
          filter.type &&
          (filter.type && filter.type.toLocaleLowerCase() == "datetime")
        )
          return true;
      }

    }

  }
  return false;
}

const _initFilterValue = function () {
  var filterValue = {};
  //根据列筛选属性，生成相应的保存输入值的对象
  if (typeof props.mainParmas == "undefined") {
    //如果上一次模糊查询参数为空，则从模糊查询列来组合
    for (var i in props.columnFilter) {
      var filter = props.columnFilter[i];
      if (typeof filter == 'string') {
        filterValue[filter] = ''
      } else if (typeof filter == 'object') {
        if (filter.prop) {
          if (_isUse(filter.prop))
            if (filter.defaultValue == undefined) {
              filterValue[filter.prop] = "";
            } else {
              filterValue[filter.prop] = filter.defaultValue;
            }
        }
      }
    }
    columnFilterValue = Object.assign(columnFilterValue, filterValue);
  } else {
    columnFilterValue = Object.assign(columnFilterValue, props.mainParmas);
  }
}



const _isUse = function (prop) {
  //如果该筛选面板是固定的，则只启用固定列的筛选框，如果是非固定列的，则只启用非固定列的筛选框
  var f = props.columns.some((item) => {
    if (item.dataIndex == prop) {
      return true;
    } else return false;
  });
  if (!f) {
    return false;
  }
}

const _getDateString = function () {
  isCleanFilterChange.value = false;
  hasfilterValueChange.value = true;
  _emitFilter();
}

const _emitFilter = function () {
  //console.log("触发筛选动作之前!");
  //在非清空筛选值的情况才会提交列筛选改变事件，因为清空筛选值也会触发输入框、下拉框等的值改变事件并调用该方法
  if (!isCleanFilterChange.value) {
    emit("ColumnFilter", _changeFormat(columnFilterValue));
  }
  hasfilterValueChange.value = false;
  isCleanFilterChange.value = false;
}

const getLeft = function (item: TableColumn) {
  let left = 0
  if (props.showIndex) {
    left += 60
  }
  if (props.rowSelection) {
    left += 50
  }
  for (let i = 0; i < props.columns.length; i++) {
    if (typeof props.columns[i].width == 'number') {
      if (i > 0) {
        let width = 0
        if (typeof props.columns[i - 1].width == 'number') {
          // @ts-ignore
          width = props.columns[i - 1].width
        }
        left = left + width
      }
      if (item.dataIndex == props.columns[i].dataIndex) {
        return left + 'px'
      }
    }
  }
  return left + 'px'
}

const getRight = function (item: TableColumn) {
  let bRet = ifContainScrollY()
  let right = 0
  if (bRet) {
    right = 17
  }
  //先过滤出需要进行计算的对象
  let target = props.columns.filter((item) => {
    return item.fixed == 'right'
  })
  for (let i = target.length - 1; i >= 0; i--) {
    if (typeof target[i].width == 'number') {
      if (i < target.length - 1) {
        let width = 0
        if (typeof target[i + 1].width == 'number') {
          // @ts-ignore
          width = target[i + 1].width
        }
        right = right + width
      }
      if (item.dataIndex == target[i].dataIndex) {
        return right + 'px'
      }
    }
  }
  return right + 'px'
}

const ifContainScrollY = function (): boolean {
  let bRet = false
  const targetTable = $('#' + props.tableID);
  const tableBodyEL = targetTable.find('.ant-table-body').get(0); //表格主体
  if (tableBodyEL) {
    if (
      tableBodyEL.scrollHeight == tableBodyEL.clientHeight
    ) {
      bRet = true
    }
  }
  return bRet
}


//把数据的格式转换为最终后台可接受的格式，例如后台接口要求是数字的，text输出的都是string，必须要转换
const _changeFormat = function (filterVal) {
  for (var i in filterVal) {
    var val = filterVal[i];
    for (var j in props.columnFilter) {
      let temp = props.columnFilter[j]
      if (typeof temp == "object") {
        if (temp.prop == i) {
          //目前先仅仅处理number
          if (temp.dataType == "number") {
            if (val != null && val != undefined && val != "")
              filterVal[i] = parseFloat(val);
          }
          break;
        }

      }

    }
  }
  return filterVal;
}

//清空筛选条件
const cleanFilter = function () {
  for (var i in columnFilterValue) {
    var item = columnFilterValue[i];
    if (typeof item !== "function") {
      columnFilterValue[i] = null;
    }
  }
  isCleanFilterChange.value = true;
  emit("ColFilterChange", columnFilterValue);
}

const _isTextBox = function (prop) {
  //判断系统是否自动生成文本框 
  for (var i in props.columnFilter) {

    var filter = props.columnFilter[i];
    if (typeof filter == "object") {
      if (filter.prop && filter.prop == prop) {
        //设置有prop时以prop判断，没有设置，仅仅设置了空属性时，如columnFilter[i]=prop
        if (
          filter.type &&
          (filter.type == "TextBox" || filter.type == undefined)
        )
          return true;
      } else if (!filter.prop && filter == prop) return true;
    } else if (typeof filter == 'string') {
      if (filter == prop) {
        return true
      }
    }
  }

  return false;
}
//检查是否下拉框
const _isCombox = function (prop) {
  for (var i in props.columnFilter) {
    var filter = props.columnFilter[i];
    if (typeof filter == 'object') {
      if (filter.prop && filter.prop == prop)
        if (filter.type && filter.type.toLocaleLowerCase() == "combox") return true;
    }

  }
  return false;
}
const _isCheckbox = function (prop) {
  for (var i in props.columnFilter) {
    var filter = props.columnFilter[i];
    if (typeof filter == 'object') {
      if (filter.prop && filter.prop == prop)
        if (filter.type && filter.type.toLocaleLowerCase() == "checkbox") return true;
    }

  }
  return false;
}
const _isTree = function (prop) {
  for (var i in props.columnFilter) {
    var filter = props.columnFilter[i];
    if (typeof filter == 'object') {
      if (filter.prop && filter.prop == prop)
        if (filter.type && filter.type == "Tree") return true;
    }

  }
  return false;
}

/*监听列筛选值的改变采用以下机制
* 1、当下拉框改变时，触发筛选动作
* 2、当文本框改变时，不触发筛选动作，记录改变状态
* 3、当文本框失去焦点时，判断改变状态，如果发现筛选值已经改变，触发筛选动作，否则不触发
*/
const _onSelectChange = function () {
  isCleanFilterChange.value = false;
  _emitFilter();
}
const _onTextChange = function () {
  isCleanFilterChange.value = false;
  hasfilterValueChange.value = true;
}
const _onTextBlur = function () {
  if (hasfilterValueChange.value) {
    let temp = _changeFormat(columnFilterValue)
    emit("ColumnFilter", temp);
  }
}
const _onEnter = function (e) {
  //屏蔽掉td的回车事件，是因为在win10自带的浏览器中，会出现不能正确响应回车事件的问题。
  if (!!window.ActiveXObject || "ActiveXObject" in window) {
    //判断是否是IE浏览器
    $(e.currentTarget).find(".a-input__inner").blur(); //让当前的输入框失去焦点
  }
}

const showSelection = computed(() => {
  let bRet = typeof props.rowSelection != 'undefined'
  return bRet
});

const setColFilterWidth = () => {
  //因为antd-v数据会自动撑开列，因此在滚动条调整的时候，调整列宽
  const targetTable = $('#' + props.tableID);
  const tableHeaderEL = targetTable.find('.ant-table-thead').get(0); //表头
  if (tableHeaderEL) {
    const targetTR = targetTable.find('.ant-table-thead').find('tr')
    const tds = targetTR[0].children as HTMLCollectionOf<HTMLElement>; //表头生成的列
    const filtertds = targetTR[1].children as HTMLCollectionOf<HTMLElement>
    let arrayLength = filtertds.length
    for (let i = 0; i < arrayLength; i++) {
      filtertds[i].style.left = tds[i].style.left
      filtertds[i].style.right = tds[i].style.right //根据表头调整位置
    }
  }
}

const onscroll = () => {
  //监听表格滚动事件
  let targetTable = $("#" + props.tableID).find(".ant-table-body")
  if (targetTable.length > 0) {
    $("#" + props.tableID).find(".ant-table-body").on("scroll", function () {
      setColFilterWidth()
    });
  } else {
    $("#" + props.tableID).find(".ant-table-content").on("scroll", function () {
      setColFilterWidth()
    });
  }


}
watchEffect(() => {
  if (props.externalQueryParama) {
    for (let i in props.externalQueryParama) {
      if (i != undefined) {
        columnFilterValue[i] = props.externalQueryParama[i]
      }
    }
    _emitFilter();
  }
});


onBeforeMount(() => {
  _initFilterValue()

})

onMounted(() => {
  onscroll()
})

onUpdated(() => {
  nextTick(() => {
    setColFilterWidth()
  })
})

onUnmounted(() => {
  //组件卸载的时候，要取消滚动条的监听
  $("#" + props.tableID).find(".ant-table-body").off("scroll");
  $("#" + props.tableID).find(".ant-table-content").off("scroll");
})

</script>

<style>
.custom-table:deep() tr[class='filterTR']>td {
  padding: 1px 0px !important;
  white-space: nowrap;
}
</style>
