<template>
	<div class="xd-table-select">
		<div class="xd-table-select__table" :style="{maxHeight: maxHeight}">
			<xd-table
				ref="table"
				:key="tableKey"
				v-if="headers.length > 0"
				:get-link="getLink"
				:headers="headers"
				:list="list"
				:is-border="border"
				@onClick="handleClickBtn"
				@change="handleInputChange"
			></xd-table>
		</div>
		<div class="xd-table-select__btn" v-if="isOne && list.length === 0">
			<el-button type="primary" @click="handleOpen()" :disabled="disabled">{{btnName}}</el-button>
		</div>
		<div class="xd-table-select__btn" v-if="!isOne">
			<el-button type="primary" @click="handleOpen()" :disabled="disabled">{{btnName}}</el-button>
		</div>
		<xd-dialog
			:title="title"
			:width="width"
			:show.sync="dialogShow"
			v-if="dialogShow"
			@onClose="handleClose"
		>
			<xd-cascade-panel
				v-if="dialogShow"
				v-model="selectListValue"
				ref="cascade"
				:key="tablePanel"
				:size="size"
				:disabled="disabled"
				:default-value="selectListValue"
				:setting="setting"
				:required="required"
				:list="ableSelectList"
			></xd-cascade-panel>
			<template slot="btn">
				<el-button
					size="medium"
					@click="handleClose"
				>取 消</el-button>
				<el-button
					size="medium"
					type="primary"
					:disabled="selectListValue.length === 0"
					@click="handleCascadeCustom"
				>确 定</el-button>
			</template>
		</xd-dialog>
	</div>
</template>

<script>
  import emitter from 'element-ui/src/mixins/emitter';
  import XdTable from "@/components/XdTable";
  import XdDialog from "@/components/XdDialog";
  import XdCascadePanel from "./XdCascadePanel";

  export default {
    name: "XdTableCascade",
		components: {
      XdDialog,
      XdTable,
      XdCascadePanel
		},
    mixins: [emitter],
		props:{
      defaultValue: {
        type: Array,
        default() {
          return []
        },
      },

      maps: {
        type: Object | null,
        default() {
          return null
        },
      },

      setting: {
        type: Object,
        default() {
          return {
            selectList: [],
            btnName: '指定区域',
            width: '600px',
            border: true,
            headers: [],
						isOne: false,
					}
        },
      },

      disabled: {
        type: Boolean,
        default: false,
      },

      size: {
        type: String,
        default: 'medium', //medium / small / mini
      },

      placeholder: {
        type: Object,
        default() {
          return {
          }
        },
      },

      required: {
        type: Boolean,
        default: false,
      },

      //是否启用自定义校验器
      useCustomRules: {
        type: Boolean,
        default: false,
      },

      //数字字符串 转 数字
      isNumber: {
        type: Boolean,
        default: true,
      },

      //自定义方法
      handleCustom: {
        type: Function || null,
        default: null
      },

		},
    computed:{
      operate(){
        return {
          type: 'operate',
          align: 'center',
          prop: 'operate',
          minWidth: 200,
          label: '操作',
          values: [
            {ui: 'text-button', name: '修改', type: 'primary',},
            {ui: 'text-button', name: '删除', type: 'danger',},
          ]
        }
      }
    },
		data(){
      return {
        tableKey: 'tableKey',
        btnName: '指定区域',
        border: true,
        isOne: false,

        headers: [
          {type: 'normal', sort: true, prop: 'label', align: 'center', minWidth: 200, label: '可配送区域'},
          {type: 'tag', prop: 'regions', align: 'center', minWidth: 200, label: '可配送区域'},
          this.operate,
        ],
        width: '600px',
        maxHeight: '300px',
        title: '选择配送区域',
        list: [], //已选中城市列表
				is_var_price: {}, //表单字段为价格

				//dialog and city select data
        tablePanel: 'tablePanel',
        dialogShow: false,
				rowIndex: null, //编辑数据
				row: null,
        selectListSource: [], //原始可选列表数据树
        selectListValue: [], //当前次选中的值
        ableSelectList: [], //可选列表数据树
			}
		},

		created(){
      if (typeof this.handleCustom !== 'function') {
        throw new Error(`this.handleCustom()自定义访问未定义`)
      }

      if (this.setting['width'] !== undefined) this.width = this.setting['width'];
      if (this.setting['maxHeight'] !== undefined) this.maxHeight = this.setting['maxHeight'];
      if (this.setting['title'] !== undefined) this.title = this.setting['title'];
      if (this.setting['border'] !== undefined) this.border = this.setting['border'];
      if (this.setting['btnName'] !== undefined) this.btnName = this.setting['btnName'];
      if (this.setting['isOne'] !== undefined) this.isOne = this.setting['isOne'];

      if (this.setting['headers']
				&& this.$xdHelper.checkVarType(this.setting.headers) === 'array'
			){
        this.headers = this.setting['headers'].map(item=>{
          if(item.type === 'input'){
            item.disabled = this.disabled
          }
          return item;
        }).filter(item=>{
          return item.type !== 'operate'
        });
        this.headers.push(this.operate)
      }

      if(this.setting.selectList
				&& this.$xdHelper.checkVarType(this.setting.selectList) === 'array'
			) {
        this.selectListSource = this.setting.selectList;
      }
      else {
        let domeData = [{
					"value": "1",
					"label": "北京",
					"children": [
						{"value": "jfb1", "label": "北京"},
						{"value": "bj-test1", "label": "北京-测试"}
					]
				}];
       	throw new Error(`面板可选选择数据格式：\nthis.setting.selectList = ${JSON.stringify(domeData, null, 2)}`)
			}

      this.headers.map(item => {
        if (item.isPrice) {
          this.is_var_price[item.prop] = true;
        }
      });


      this.handleMapToList();
		},

		methods: {
      handleInputChange(){
        this.$nextTick(() => {
          this.update();
        });
			},
      handleClose(){
        this.selectListValue = [];
        this.ableSelectList = [];
      	this.dialogShow = false;
        this.rowIndex = null;
        this.row = null;
			},

			getRootValueForLeafValue(){
        let list = [];
        const handle = (root) => {
          let len = root.length;
          for (let i = 0; i < len; i++) {
            //有子节点并且半选时候
            if (root[i].children && root[i].children.length > 0) {
              handle(root[i].children);
            }
            else{
              if(root[i].checked) list.push(root[i]);
						}
          }
        };
        handle(this.ableSelectList);
        this.selectListValue = list.map(item=>{
          return item.value
				})
			},

      handleCascadeCustom(){
        if (typeof this.handleCustom === 'function') {
          let nodes = this.$refs['cascade'].getRootNodes();
          let list = [];
          const handle = (root) => {
            let len = root.length;
            for (let i = 0; i < len; i++) {

              //有子节点并且半选时候
              if(root[i].children.length > 0
								&& root[i].indeterminate === true
							) {
                handle(root[i].children);
							}
              else {
                if(root[i].checked) list.push({
                  ...this.$refs['cascade'].getNodeData([root[i]])[0],
									...root[i].data
								});
							}
            }
          };
          handle(nodes);
					this.handleCustom({
						action: 'select',
						data: {
              list: list,
							cb: (item) => {
                let list = this.$xdHelper.cloneDeep(this.$refs.table.getTableData());
                if(this.rowIndex === null) list.unshift(item);
                else list.splice(this.rowIndex, 1, {
                  ...list[this.rowIndex],
                  value: item.value,
                  label: item.label,
                  regions: item.regions,
								});
                this.list = this.$xdHelper.cloneDeep(list);
                this.handleClose();
                this.$nextTick(() => {
                  this.update();
                });
							}
						}
					});
        }
			},

      handleOpen(){
        this.dialogShow = true;
        this.tablePanel = this.$xdHelper.randomChar(20);
        this.ableSelectList = this.eachNode();
        if(this.rowIndex !== null) this.getRootValueForLeafValue();
			},

      /**
       * @description 处理点击事件按钮跳转
       * @param row
       * @param value
       * @param index
			 * @param rowIndex
       */
      handleClickBtn({row, value, index, rowIndex}){
        if(index === 1) {
          let tableData = this.$xdHelper.cloneDeep(this.$refs.table.getTableData());
          tableData.splice(rowIndex, 1);
          this.list = tableData;
          this.tableKey = this.$xdHelper.randomChar(20);
          this.$nextTick(()=>{
            this.update();
					});
				}
        if(index === 0) {
          this.rowIndex = rowIndex;
          this.row = row;
          this.handleOpen();
				}
			},

			checkValueExistList(value){
        let source = this.$xdHelper.cloneDeep(this.$refs.table.getTableData());
        if(this.rowIndex !== null) source.splice(this.rowIndex,1);
        let list = source.filter(item => {
          return item.value.filter(val=>{
            return val === value
					}).length > 0;
        });
        return list.length > 0;
			},

			getChecked(value){
        if(this.row === null) return false;
   			return this.row.value.filter(item=>{
          return value === item;
				}).length > 0
			},

			/**
			 * @description 初始化列表数据
			 */
			eachNode(){
			  let time = new Date().getTime();
        let list = [];

        //树便利
        const handle = (root, isRoot, children)=>{
          let len = root.length;
          for(let i = 0; i < len; i++) {
            let temp = {
              value: root[i].value,
              label: root[i].label,
							length: 0,
              disabledCount: 0,
							checked: this.getChecked(root[i].value) || children.checked === true,
              disabled: this.checkValueExistList(root[i].value),
            };

            if (root[i].children && root[i].children.length > 0) {
              temp.children = [];
              temp.length = root[i].children.length;
              handle(root[i].children, false, temp);
            }

            if (isRoot) {
              children.push(temp);
            } else {
              if (temp.disabled){
                children.disabledCount++;
							}
              if (children.disabledCount === root.length) {
                children.disabled = true;
							}
							children.children.push(temp);
            }

					}
				};

        handle(this.selectListSource, true, list);
        console.log('eachNode', list, this.list, new Date().getTime() - time , 'ms');
        return list;

			},

			/**
			 * @description 处理点击链接按钮跳转
			 * @param row
			 * @param value
			 * @param index
			 */
      getLink({row, value, index}){
        if(typeof this.handleCustom === 'function') {
          return this.handleCustom({action: 'link', data: {row, value, index}})
				}
        return `/`;
			},

			getPrice(item, type='in'){
   			let temp = {};
        Object.keys(item).map(key => {
          if (this.is_var_price[key]) {
            let price = item[key];
            if (this.$xdHelper.checkVarType(price) === 'string') {
              price = Number(item[key])
            }
            if (price){
              if (type === 'in') price = this.$xdHelper.divisionFloatNumber(price, 100);
              else price = this.$xdHelper.multiplyFloatNumber(price, 100);
						}
            else price = item[key];
            temp[key] = price;
          }
          else {
            temp[key] = item[key];
          }
        });
        return temp
			},

      /**
       * @description 返回映射关系对象数据（需要自己实现）
			 * 把内部数据转化为返回数据格式
       */
      handleListToMap() {
        let tableData = this.$xdHelper.cloneDeep(this.$refs.table.getTableData());
        tableData = tableData.map(item=>{
          return this.getPrice(item, 'out');
				});
        if(!this.required) {
          return tableData
				}
        return this.handleCustom({action: 'filter', data: tableData});
      },

      /**
       * @description 初始化映射关系到数据列表(需要自己实现)
			 * 把默认数据转化为内部数据
       */
      handleMapToList() {
        if(this.defaultValue
					&& this.$xdHelper.checkVarType(this.defaultValue) === 'array'
					&& this.defaultValue.length > 0
				) {
          this.list = this.$xdHelper.cloneDeep(this.defaultValue).map(item=>{
            return this.getPrice(item);
					});
          this.$nextTick(()=>{
            this.update();
					})
				}
      },

      //插件系统方法///////////////////////////////////////
      /**
       * @description 获取Maps中键与值
       * @param type {boolean} 返回值类型  true=>获取键  false=>值
       * @param keyword {string} 查找关键字
       * @return {null|string} null=>未找到  string=>找到
       */
      getMap(keyword, type) {
        let maps = null;
        let value = null;
        if (this.maps !== null && !this.$xdHelper.isEmpty(this.maps)) {
          maps = this.$xdHelper.cloneDeep(this.maps);
        }

        //先默认maps关系中找
        Object.keys(this.defaultMap).map(ky => {
          //获取键
          if (type) {
            if (this.defaultMap[ky] === keyword) {
              value = ky;
            }
          } else {
            if (this.defaultMap[keyword]) value = this.defaultMap[keyword];
          }
        });

        //无外部map关系并且在默认关系表中无键
        if (value === null && maps === null) {
          //console.log('1')
          return null;
        }

        //无外部map关系并且在默认关系表中键
        if (value !== null && maps === null) {
          //console.log('2', value)
          return value;
        }

        //有外部map关系进行查找
        Object.keys(maps).map(ky => {
          //获取键
          if (type) {
            if (maps[ky] === keyword) {
              value = ky;
            }
          } else {
            if (this.maps[keyword]) value = this.maps[keyword];
          }
        });
        //console.log('3')
        return value;

      },


      /**
			 * @description 需要校验检查参数是正确处理方法
       */
			checkParams(){
        if (!this.required) return this.handleListToMap();

        //校验成功
        return this.handleListToMap();
			},

      /**
			 * @description 双向绑定数据处理
       */
			update(){
        this.$emit('input', this.checkParams());
        if (this.$parent.$options['componentName'] === 'ElFormItem') {
          this.dispatch('ElFormItem', 'el.form.change', [this.checkParams()]);
        }
			},


		}
  }
</script>

<style scoped lang="scss">
	.xd-table-select {
		&__table {
			overflow-y: auto;
		}
		&__btn {
			padding-top: 10px;
			display: flex;
			justify-content: flex-start;
			align-items: center;
			& > *:nth-child(2) {
				margin-left: 10px;
				color: #999;
				& span {
					padding: 0 2px;
				}

			}
		}
	}

	@media screen and (max-width: 768px) {
		.xd-table-select {
		}
	}
</style>
