<template>
  <div class="aos-ref">
    <el-select
      v-if="editable && showType === 'select'"
      ref="aosRef"
      v-model="refValue"
      filterable
      :multiple="multiple"
      :multipleLimit="multipleLimit"
      :collapse-tags="collapseTags"
      :clearable="clearable"
      :disabled="disabled"
      :placeholder="placeholder"
      default-first-option
      :allow-create="allowCreate"
      remote
      :remote-method="handleRemoteMethod"
      :loading="false"
      @change="handleRefChange"
      @visible-change="handleVisibleChange"
      @clear="handleClear"
      @blur="handleBlur"
      @focus="handleFocus"
      @remove-tag="handleRemoveTag">
      <template v-if="refType === 'select'">
        <el-option
          v-for="item in options"
          :key="item.code"
          :label="item.value"
          :value="item.code">
        </el-option>
      </template>
      <template v-if="refType === 'tree'">
        <el-option-group
          class="aos-ref__option-tree"
          :key="options.label"
          :label="options.label">
          <div v-if="refType === 'tree'" style="padding: 0px 20px">
            <el-input
              placeholder="输入关键字进行过滤"
              v-model="filterText">
            </el-input>
          </div>
          <el-option
            style="height: 0px;"
            v-for="item in treeOptionFlat"
            :key="'tree_'+item.code"
            :label="item.value"
            :value="item.code"
            >
          </el-option>
          <el-option class="aos-ref__option-tree-option" key="tree_options">
            <el-tree
              class="aos-ref__option-tree-main"
              v-if="refType === 'tree'"
              ref="tree"
              node-key="code"
              :data="options"
              :props="defaultProps"
              :default-expand-all="defaultExpandAll"
              :filter-node-method="filterNode"
              :default-checked-keys="defaultCheckedKeys"
              @node-click="handleNodeClick"
              :show-checkbox="multiple && showCheckbox"
              @check="handleCheck"
              :expand-on-click-node="true"
              >
              <span class="aos-ref__option-tree-main-item" slot-scope="{ node }">
                <span>{{ node.label }}</span>
              </span>
            </el-tree>
          </el-option>
        </el-option-group>
      </template>
      <template slot="append" v-if="appendIcon">
        <i class="el-icon-plus" @click="handleAppendPlusClick"></i>
      </template>
    </el-select>
    <div v-if="!editable" class="el-form-item__content aos-form-input-text">
      {{onlyTranslate ? translateRefValueLable : refValueLable}}
    </div>
    <div v-if="editable && showType === 'checkbox' && multiple" class="aos-defdoc__container">
      <!-- <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox> -->
      <el-checkbox-group v-model="refValue" @change="handleCheckedChange">
        <el-checkbox v-for="item in options" :label="item.code" :key="item.code">{{item.value}}</el-checkbox>
      </el-checkbox-group>
    </div>
    <div v-if="editable && showType === 'button' && multiple" class="aos-defdoc__container">
      <el-checkbox-group v-model="refValue" @change="handleCheckedChange" size="mini">
        <el-checkbox-button v-for="item in options" :label="item.code" :key="item.code">{{item.value}}</el-checkbox-button>
      </el-checkbox-group>
    </div>
    <div v-if="editable && showType === 'checkbox' && !multiple" class="aos-defdoc__container">
       <el-radio-group v-model="refValue" @change="handleRadioChange">
        <el-radio v-for="item in options"  :label="item.code" :key="item.code">{{item.value}}</el-radio>
      </el-radio-group>
    </div>
    <div v-if="editable && showType === 'button' && !multiple" class="aos-defdoc__container">
       <el-radio-group v-model="refValue" @change="handleRadioChange" size="mini">
        <el-radio-button v-for="item in options"  :label="item.code" :key="item.code">{{item.value}}</el-radio-button>
      </el-radio-group>
    </div>
  </div>
</template>

<script>
import debounce from 'throttle-debounce/debounce';
import cloneDeep from 'lodash/cloneDeep';
export default {
  name: 'AosRef',
  props: {
    // 参照对应的编码
    refCode: {
      type: String,
      required: true,
     // default:'woTypeRef'
    },
    value: {
      type: [String, Array],
      required: true
    },
    // 编辑状态
    editable: {
      type: Boolean,
      required: true,
      default: true
    },
    // 防抖
    debounce: {
      type: Number,
      default: 300
    },
    // 参照下拉列表的位置
    placement: {
      type: String,
      default: 'bottom-start'
    },
    // 提示
    placeholder: {
      type: String,
      default: '请选择'
    },
    // 是否可清空
    clearable: {
      type: Boolean,
      default: true
    },
    // 禁用状态
    disabled: {
      type: Boolean,
      default: false
    },
    // 是否多选
    multiple: {
      type: Boolean,
      default: false
    },
    // 是否折叠多选
    collapseTags: {
      type: Boolean,
      default: false
    },
    // 多选限制
    multipleLimit: {
      type: Number,
      default: 0
    },
    // 查询参数
    queryParams: {
      type: Object,
      default: function() {
        return {};
      }
    },
    // 过滤参数
    filters: {
      type: Array,
      default: function () {
        return []
      }
    },
    // 默认选中第一项
    firstDefault: {
      type: Boolean,
      default: false
    },
    // 参照显示的类型,默认是输入框,暂时未启用
    showType: {
      type: String,
      default: 'select',
      validator: function (value) {
        return ['select', 'table', 'button', 'checkbox'].indexOf(value) !== -1
      }
    },
    // 只翻译，适用于只显示非编辑状态
    onlyTranslate: {
      type: Boolean,
      default: false
    },
    // 只翻译时外部传回来的值,需要和onlyTranslate配合使用
    translateRefValueLable: {
      type: String,
      default: ''
    },
    // 是否允许通过输入框创建新的条目
    allowCreate : {
      type: Boolean,
      default: false
    },
    // 是否显示尾部的添加
    appendIcon: {
      type: Boolean,
      default: false
    },
    customerUrl: {
      type: String
    },
    noRefCode: {
      type: Boolean,
      default: false
    },
    ormCode: {
      type: String
    },
    ormName: {
      type: String
    },
    ormData: {
      type: String
    },
    ormStatus: {
      type: String
    },
    // 是否不使用请求缓存
    immediate: {
      type: Boolean,
      default: false
    },
    defaultExpandAll: {
      type: Boolean,
      default: false
    },
    onlyTreeLeaf: {
      type: Boolean,
      default: true
    },
  },
  computed: {
    emitData () {
      let emitData = '';
      if (this.multiple) {
        if (this.refValue && this.refValue.length > 0) {
          this.refValue.forEach((item,index) => {
            emitData += item;
            if (index < this.refValue.length - 1) {
              emitData += ',';
            }
          });
        }
      } else {
        emitData = this.refValue;
      }
      return emitData
    },
    emitFullData () {
      let emitFullData = [];
      let options = this.options
      if (this.refType === 'tree') {
        options = this.treeOptionFlat
      }
      if (this.multiple) {
        if (this.refValue && this.refValue.length > 0) {
          this.refValue.forEach(item => {
            const data = this.$_.find(options, { code: item });
            if (data) {
              emitFullData.push(data)
            }
          });
        }
      } else {
        const data = this.$_.find(options, { code: this.refValue });
        if (data) {
          emitFullData.push(data)
        }
      }
      return emitFullData
    }
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    },
    // refValue: function (val, oldVal) {
    //   if (!this.onlyTranslate && this.options && this.options.length > 0 && val && !this.$_.isEqual(val, oldVal)) {
    //     this.init()
    //   }
    // },
    filters:{
      handler: function (val, oldVal) {
        if (!this.onlyTranslate && val && Object.keys(val).length > 0) {
          this.init()
        }
      },
      deep: true
    },
    value: function (val, oldVal) {
      if (!this.onlyTranslate && !this.$_.isEqual(val, oldVal)) {
        if(this.multiple && this.refType === 'tree'){
           if (this.emitData !== val) {
               this.init()
              }
        }else{
          this.init()
        }
      }
    },
    refCode: function (val, oldVal) {
      if (!this.onlyTranslate && !this.$_.isEqual(val, oldVal)) {
        this.init()
      }
    },
    customerUrl: function (val, oldVal) {
      if (!this.onlyTranslate && !this.$_.isEqual(val, oldVal)) {
        this.init()
      }
    }
  },
  created () {
    this.debounceHandleEmitChange = debounce(10, this.handleEmitChange)
    if (!this.onlyTranslate) {
      this.init()
      this.firstInit = true
    }
  },
  data() {
    return {
      options: [],
      refValue: '',
      refValueLable: '',
      firstInit: true,
      debounceHandleEmitChange: '',
      refType: 'select',
      filterText: '',
      treeRefValueObject: {},
      treeOptionFlat: [],
      defaultProps: {
        children: 'children',
        label: 'value'
      },
      showCheckbox:true,
      defaultCheckedKeys:[]
    };
  },
  methods: {
    handleCheckChange(data, checked, indeterminate) {
        console.log(data, checked, indeterminate);
      },
      handleCheck(data, checkedData) {
        const refValue = []
        // const node =  this.$refs.tree.getNode(data)
        // if(node.expanded){
        //   this.$nextTick(()=>{
        //     node.expanded = true
        //     node.childNodes.forEach(event=>event.expanded = true)
        //   })
        // }
        // console.log('---',data, checkedData,node);
        checkedData.checkedNodes.forEach(item=> {
          if(item.isLeaf){
            refValue.push(item.code)
          }
        })
        this.refValue = refValue
        this.defaultCheckedKeys = refValue
        this.setRefValue(refValue)
        this.handleEmitChange()
      },
    getTreeFilter () {
      if (this.filterText !== '') {
        this.$nextTick(() => {
          this.$refs.tree.filter(this.filterText);
        })
      }
    },
    handleNodeClick (data) {
      if (this.onlyTreeLeaf && data.isLeaf) {
        this.setTreeRefValue(data);
        this.debounceHandleEmitChange()
        this.$refs.tree.setChecked(data, true); //设置为未选中
        var node = this.$refs.tree.getNode(data); //获取节点
        if (node.childNodes.length > 0) {
          this.treeToList(node).map((item) => {
            if (item.childNodes.length <= 0) {
              this.$refs.tree.setChecked(item, true);
            }
          });
        }
      } else if (!this.onlyTreeLeaf) {
        this.setTreeRefValue(data);
        this.debounceHandleEmitChange()
      }
    },
    setTreeRefValue (data) {
      console.log('setTreeRefValue',data)
      this.treeRefValueObject[data.code] = data
      const code = data.code
      const label = data.value
      this.refValueLable = ''
      if (this.multiple) {
        if (this.refValue && Array.isArray(this.refValue) && this.refValue.indexOf(code) < 0) {
          this.refValue.push(code)
        }
        this.refValue.forEach((key,index) => {
          this.refValueLable = this.refValueLable + this.treeRefValueObject[key].value 
          if (index < this.refValue.length - 1) {
            this.refValueLable = this.refValueLable + ','
          }
        })
      } else {
        this.refValue = code
        this.refValueLable = label
      }
    },
    filterNode(value, data) {
      if (!value) return true;
      return data.value.indexOf(value) !== -1;
    },
     getLableByCode () {
      let paramsData = ''
      if (this.multiple) {
        paramsData = this.refValue.join(',')
      } else {
        paramsData = this.refValue
      }
      this.$optimizeHttp({
        url: '/core/api/ref/translate/' + this.refCode,
        method: 'get',
        params: {
          code: paramsData
        }
      }).then((res) => {
        const resData = cloneDeep(res.data)
        this.refValueLable = '';
        if (this.refValue.length > 0) {
          if (this.multiple) {
            this.refValue.forEach((item, index) => {
              const sourceData = this.$_.find(resData, { code: item });
              if (sourceData) {
                if (this.refType === 'tree') {
                  this.treeRefValueObject[sourceData.code] = sourceData
                  if (!this.$_.find(this.treeOptionFlat, { code: sourceData.code})) {
                    this.treeOptionFlat.push(sourceData)
                  }
                }
                if (!this.$_.find(this.options, { code: sourceData.code})) {
                  this.options.push(sourceData)
                }
                this.refValueLable += sourceData.value;
                if (index < this.refValue.length - 1) {
                  this.refValueLable += ',';
                }
              }
            });
          } else {
            const sourceData = this.$_.find(resData, { code: this.refValue });
            if (sourceData) {
              if (this.refType === 'tree') {
                this.treeRefValueObject[sourceData.code] = sourceData
                if (!this.$_.find(this.treeOptionFlat, { code: sourceData.code})) {
                  this.treeOptionFlat.push(sourceData)
                }
              }
              if (!this.$_.find(this.options, { code: sourceData.code})) {
                this.options.push(sourceData)
              }
              this.refValueLable = sourceData.value;
            } else {
              this.refValueLable = '';
            }
          }
        }
      })
    },
    handleCheckedChange (data) {
      this.refValue = data
      this.setRefValue(data)
      this.handleEmitChange()
    },
    handleRadioChange (data) {
      this.refValue = data
      this.setRefValue(data)
      this.handleEmitChange()
    },
    handleEmitChange () {
      this.$emit('change', this.emitData, this.emitFullData)
    },
    handleAppendPlusClick () {
      this.$emit('plus-click')
    },
    checkOptionsIsTreeType (options) {
      let isTreeType = false
      if (options && options.length > 0) {
        for (let index = 0; index < options.length; index++) {
          const element = options[index];
          if (element.children) {
            isTreeType = true
          }
        }
      }
      if (isTreeType) {
        this.refType = 'tree'
      } else {
        this.refType = 'select'
      }
    },
    setTreeDataLeaf (parent, option) {
      if (option && Array.isArray(option) && option.length > 0) {
        option.forEach(item => {
          if (parent && parent.level) {
            item.level = parent.level + 1
          } else {
            item.level = 1
          }
          if (item.children && Array.isArray(item.children) && item.children.length > 0) {
            item.isLeaf = false
            this.setTreeDataLeaf(item, item.children)
          } else {
            item.isLeaf = true
          }
        })
      }
    },
    flatTreeData (option) {
      if (option && Array.isArray(option) && option.length > 0) {
        option.forEach(item => {
          this.treeOptionFlat.push(item)
          if (item.children && Array.isArray(item.children) && item.children.length > 0) {
            this.flatTreeData(item.children)
          }
        })
      }
    },
    /**
     * @description: 参照远程搜索
     * @param {type} 输入框的值
     * @return:
     */
    handleRemoteMethod(queryString) {
      if (!this.refCode) {
        this.$message({
          type: 'error',
          message: this.refCode + '对应的 refCode 不能为空.'
        });
        return;
      }
      let submitData;
      const filters = Object.prototype.toString.call(this.filters) === '[object Array]' ? this.filters : []
      const content = queryString ? queryString : ''
      if (this.showType === 'dialog') {
        submitData = {
          content: content,
          page: this.page,
          size: this.size,
          filters: filters
        };
      } else {
        submitData = {
          content: content,
          filters: filters
        };
      }
      // let queryParamsKeys = Object.keys(this.queryParams);
      // if (queryParamsKeys.length > 0) {
      //   queryParamsKeys.forEach((item) => {
      //     params[item] = this.queryParams[item];
      //   });
      // }
      let url = '/core/api/ref/simple-search/'+ this.refCode
      if (this.customerUrl) {
        url = this.customerUrl + this.refCode
        if (this.noRefCode) {
          url = this.customerUrl
        }
      }
      let http = this.$optimizeHttp
      if (this.immediate) {
        http = this.$http
      }
      return http({
        method: 'post',
        url: url,
        data: submitData
      }).then((res) => {
        if (res.status === 200) {
          let options = JSON.parse(res.data.data);
          if (!options || (Array.isArray(options) && options.length === 0)) {
            this.$emit('options-empty', true)
          }
          this.checkOptionsIsTreeType(options)
          if (this.refType === 'tree') {
            this.setTreeDataLeaf('',options)
            this.treeOptionFlat = []
            this.flatTreeData(options)
          }
          this.options = options
          if (this.firstInit && this.firstDefault) {
            this.setFirstDefault();
          }
          this.firstInit = false;
          this.getTreeFilter()
        } else {
          this.$message({
            type: 'error',
            message: '请求参照数据失败'
          });
        }
      });
    },

    /**
     * @description: 设置默认第一项,当有值的时候不设置
     * @param {type} none
     * @return: undefined
     */
    setFirstDefault() {
      if (this.multiple) {
        if (this.refValue.length <= 0) {
          this.refValue = [];
          let options = this.options
          if (this.refType === 'tree') {
            options = this.treeOptionFlat
          }
          if (options.length > 0 && options[0]) {
            this.refValue.push(options[0].code);
            this.debounceHandleEmitChange()
          }
        }
      } else {
        if (!this.refValue) {
          let options = this.options
          if (this.refType === 'tree') {
            options = this.treeOptionFlat
          }
          if (Array.isArray(options) && options[0]) {
            this.refValue = options[0].code;
            this.debounceHandleEmitChange()
          }
        }
      }
    },
    handleRefChange(data) {
      //this.defaultCheckedKeys = data
      this.refValue = data
      this.setRefValue(data);
      this.debounceHandleEmitChange()
    },
    handleVisibleChange(data) {
      this.$emit('visible-change', data);
    },
    handleRemoveTag(tag) {
       this.$emit('remove-tag', tag);
       if(this.multiple && this.refType === 'tree'){
        this.$refs.tree.setChecked(tag, false); //设置为未选中
        var node = this.$refs.tree.getNode(tag); //获取节点
        if (node.childNodes.length > 0) {
          this.treeToList(node).map((item) => {
            if (item.childNodes.length <= 0) {
              this.$refs.tree.setChecked(item, false);
            }
          });
        }
       // arr = arr.filter(item => item != value)
        this.refValue = this.refValue.filter(item=>item != tag)
        this.defaultCheckedKeys = this.defaultCheckedKeys.filter(item=>item != tag)
       }
    },
    handleClear(data) {
      if(this.multiple && this.refType === 'tree'){
          this.refValue=''
          this.defaultCheckedKeys=[]
      }
      this.$emit('clear');
    },
    handleBlur(e) {
      this.$emit('blur', e);
    },
    handleFocus(e) {
      this.handleRemoteMethod()
      this.$emit('focus', e);
    },
    setRefValue(data) {
      let copyData = void 0
      let findLabel = true
      let options = this.options
      if (this.refType === 'tree') {
        options = this.treeOptionFlat
      }
      if (this.multiple && data) {
        if (typeof data === 'string') {
          copyData = data.split(',').filter(item => item)
        } else {
          copyData = this.$_.cloneDeep(data)
        }
        this.refValueLable = '';
        if (copyData.length > 0) {
          copyData.forEach((item, index) => {
            const sourceData = this.$_.find(options, { code: item });
            if (sourceData) {
              if (this.refType === 'tree') {
                this.treeRefValueObject[sourceData.code] = sourceData
              }
              this.refValueLable += sourceData.value;
              if (index < copyData.length - 1) {
                this.refValueLable += ',';
              }
            } else {
              findLabel = false
            }
          });
        }
      } else {
        const sourceData = this.$_.find(options, { code: data });
        if (sourceData) {
          this.refValueLable = sourceData.value;
          if (this.refType === 'tree') {
            this.treeRefValueObject[sourceData.code] = sourceData
          }
        } else {
          this.refValueLable = '';
          findLabel = false
        }
      }
      if (!this.onlyTranslate && ((!this.multiple && this.refValue) || (this.multiple && Array.isArray(this.refValue) && this.refValue.length > 0)) && !findLabel) {
        this.getLableByCode()
      }
      this.debounceHandleEmitChange()
    },
    init() {
      if (this.multiple) {
        let value = this.value
        if (value) {
          value += ''
          const valueList = value.split(',')
          this.refValue = valueList.filter(item => item)
          this.defaultCheckedKeys = valueList.filter(item => item)
        } else {
          this.refValue = [];
          this.defaultCheckedKeys=[];
        }
      } else {
        this.refValue = this.value || '';
      }
      Promise.all([this.handleRemoteMethod()]).then(() =>{
        this.setRefValue(this.value);
      });
    },
    reset () {
      this.refValue = ''
      this.refValueLable = ''
    }
  }
};
</script>
