<template>
	<div class="xd-new-transfer">
		<template v-if="firstStatus && initStatus">
			<div class="xd-new-transfer__source">
				<div class='xd-new-transfer__source-search'>
					<el-input v-model="keyword" size="small" clearable></el-input>
					<el-button @click="handleSearch()" type="primary" size="small" icon="el-icon-search"></el-button>
				</div>
				<div class="xd-new-transfer__source-count">{{leftSelectedList.length}}/{{leftTableList.length}}</div>
				<el-table
					ref="leftTable"
					:data="leftTableList"
					tooltip-effect="dark"
					stripe
					border
					:height="`${height}px`"
					style="width: 100%;"
					@selection-change="handleLeftSelectionChange"

        >
					<el-table-column type="selection" width="60"  fixed align="center">
					</el-table-column>
					<el-table-column
						:label="leftListName"
						min-width="120"
					>
						<div slot-scope="scope" class="name">{{scope.row.label}}</div>
					</el-table-column>
				</el-table>
				<div class="xd-new-transfer__source-pagination" v-if="total > page_size">
					<el-pagination
						small
						:page-size="page_size"
						:current-page="page_token"
						layout="prev, pager, next"
						:total="total"
						@current-change="handleChange"
					>
					</el-pagination>
				</div>
			</div>
			<div class="xd-new-transfer__btn">
				<el-button type="primary" size="mini" @click="handleMoveLeft()" :disabled="rightSourceSelected.length === 0 || disabled">
					<xd-font-icon size="12" icon="el-icon-arrow-left"></xd-font-icon>
				</el-button>
				<el-button type="primary" size="mini" @click="handleMoveRight()" :disabled="leftSelectedList.length === 0 || disabled">
					<xd-font-icon size="12" icon="el-icon-arrow-right"></xd-font-icon>
				</el-button>
			</div>
			<div class="xd-new-transfer__selected">
				<div class="xd-new-transfer__selected-search">
					<el-input v-model="rightKeyword" size="small" clearable></el-input>
				</div>
				<div class="xd-new-transfer__source-count">{{rightSourceSelected.length}}/{{rightSourceOrgData.length}}</div>
				<el-table
					ref="multipleTable"
					:data="rightSourceData"
					tooltip-effect="dark"
					:height="`${height}px`"
					style="width: 100%;"
					stripe
					border
					@selection-change="handleRightSelectionChange">
					<el-table-column type="selection" width="60" :selectable="handleSelectable" fixed align="center"></el-table-column>
					<el-table-column
						:label="leftListName"
						min-width="120"
					>
						<div slot-scope="scope" class="name">{{scope.row.label}}</div>
					</el-table-column>
				</el-table>
				<div class="xd-new-transfer__source-pagination" v-if="total > page_size"></div>
			</div>
		</template>
		<div v-else class="xd-new-transfer-loading">
			<div class="loading-dot">
				<div></div>
				<div></div>
				<div></div>
			</div>
		</div>
	</div>
</template>

<script>
  import emitter from 'element-ui/src/mixins/emitter';
  import XdFontIcon from "@/components/XdFontIcon";
  import {Loading} from "element-ui";

  export default {
    name: "XdNewTransfer",
    components: {XdFontIcon},
    mixins: [emitter],
		props:{
      defaultValue: {
        type: Array,
        default() {
          return []
        },
      },

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

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

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

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

      placeholder: {
        type: Object,
        default() {
          return {
            //todo
            // fullPlaceholder: '请输入金额',
            // cutPlaceholder: '请输入金额',
            //todo 插件文本框所使用提示（外面传入）
          }
        },
      },

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

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

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

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

		},

		data(){
      return {
        keyword: '',
				page_size: 20,
        page_token: 1,
				total: 0,
				leftListName: '选项',
				rightListName:'选项',
				height: 300,
				firstLoading: true,

        //左边表格
        leftTableList: [], //列表数据
        leftSelectedList:[], //选中数据
      	leftSourceData: [], //原生数据


				//右侧
        rightSourceData:[],//左侧选中原生数据
        rightSourceSelected: [], //右侧选中数据
        rightSourceOrgData: [], //原生数据
        rightKeyword:'',

				firstStatus: false, //首次加载完成
				initStatus: false, //有选择ID时候需要初始化回显
			}
		},

		computed:{

		},

		watch:{
      rightKeyword:{
        immediate: true,
				handler(value){
          this.filterKey(value);
				}
			},

      firstStatus(){
        this.firstUpdate()
			},
      initStatus(){
        this.firstUpdate()
			}
		},

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

      //设置默认页面记录返回条数
      if(this.setting.page_size && this.setting.page_size > 0) {
        this.page_size = this.setting.page_size
			}

      if (this.setting.height) {
        this.height = this.setting.height
      }

      if (this.setting.firstLoading
				&& this.$xdHelper.checkVarType(this.setting.firstLoading) === 'boolean'
			) {
        this.firstLoading = this.setting.firstLoading
      }

      //是不是第一次需要加载
			if(this.firstLoading) this.initAndSearchLeft('', false);
			else this.firstStatus = true;


			//设置默认值
			if(this.$xdHelper.checkVarType(this.defaultValue) === 'array') {
				if(this.defaultValue.length > 0) {
					let labelValue = [];
					let notLabelValue = [];

					//支持[{label: 'n1', value:'v1'},{label: 'n2', value:'v2'}] or [a,b,c]
          this.defaultValue.map(item=>{
            if(this.$xdHelper.checkVarType(item) === 'object') {
              if(item.label && item.value) {
                labelValue.push(item);
							}
						}
            else{
              notLabelValue.push(item);
						}
					});

          //全是label - value格式数据
          if(notLabelValue.length === 0) {
            this.rightSourceOrgData = JSON.parse(JSON.stringify(labelValue));
            this.rightSourceData = JSON.parse(JSON.stringify(labelValue));
            this.initStatus = true;
					}

          //label - value格式数据 and  value格式
          else{
            this.handleInitShow(labelValue, notLabelValue)
					}

				}
				else {
          this.rightSourceOrgData = [];
          this.rightSourceData = [];
          this.initStatus = true;

				}
			}
			else {
        this.rightSourceOrgData = [];
        this.rightSourceData = [];
        this.initStatus = true;
			}
		},

		methods: {

      filterKey(value){
        if (value === '') this.rightSourceData = this.$xdHelper.cloneDeep(this.rightSourceOrgData);
        else {
          value = value.trim();
          this.rightSourceData = this.$xdHelper.cloneDeep(this.rightSourceOrgData).filter(item => {
            return item.label.indexOf(value) !== -1
          });
        }
			},

      handleInitShow(labelValue, notLabelValue){
        this.handleCustom({
          action: "onInit",
          data: {
            params: notLabelValue,
            cb: ({list}) => {
              this.rightSourceOrgData = JSON.parse(JSON.stringify([].concat(list, labelValue)));
              this.rightSourceData = JSON.parse(JSON.stringify([].concat(list, labelValue)));
              this.initStatus = true;
            },
          },
        });
			},


      //=========搜索=================
      handleSearch(){
        // if(!this.keyword) return;
        this.page_token = 1;
        this.initAndSearchLeft(this.keyword)
			},

      initAndSearchLeft(keyword = '',isFirst = true){
        let loading = Loading.service({});
        this.handleCustom({
          action: "onSearch",
          data: {
            params: {keyword, page_size: this.page_size, page_token: this.page_token},
            cb: ({list, total}) => {
              if (!isFirst) this.firstStatus = true;
              this.leftSourceData = this.moveTo(list, this.rightSourceData).newSource;
              this.leftTableList = this.moveTo(list, this.rightSourceData).newSource;
              this.total = total;
              loading.close();
            },
          },
        });
			},

      handleChange(page_size){
        this.page_token = page_size;
        this.initAndSearchLeft(this.keyword)
			},
      //=========搜索=================

      //=========左侧操作=================
      handleLeftSelectionChange(value){
        this.leftSelectedList = value;
			},

      handleMoveRight(){
        if(this.disabled) return;

        //获取移除后中的原生数据新列表与被移除数据
        let {newSource, moveTo} = this.moveTo(this.leftTableList, this.leftSelectedList);
        //从左侧选择列表中移除选中数据
        this.leftTableList = newSource;
        //从左侧移除数据添加到左侧列表中
        this.rightSourceData = this.addTo(this.rightSourceData, moveTo).concat(this.rightSourceOrgData);
        this.rightSourceOrgData = this.$xdHelper.cloneDeep(this.rightSourceData);
        this.filterKey(this.rightKeyword);
        this.update();
			},
			//=========左侧操作=================

      //=========右侧操作=================
      handleRightSelectionChange(value){
      	this.rightSourceSelected = value
			},

      handleMoveLeft(){
        if(this.disabled) return;
     
        //获取移除后中的原生数据新列表与被移除数据
        let {newSource , moveTo} = this.moveTo(this.rightSourceOrgData, this.rightSourceSelected);

        //从右侧选择列表中移除选中数据
        this.rightSourceData = newSource;

        //从右侧移除数据添加到左侧列表中
        this.leftTableList = this.addTo(this.leftTableList, moveTo).concat(this.leftTableList);
        this.rightSourceOrgData = this.$xdHelper.cloneDeep(newSource);
        this.rightKeyword = '';
        this.update();
			},

      handleSelectable(row, index){
        console.log(this.disabled || row.disabled === false || row.disabled === undefined);
        return this.disabled || row.disabled === false || row.disabled === undefined
			},

      //=========右侧操作=================


			/**
			 * @description 移除数组中的指定数组数据并返回新的数组与被移除数组列表
			 * @param source {Array} 原始数组
			 * @param select {Array} 指定移除数据数组
			 * @return {Object} newSource新的原始数组  moveTo被移除的数组列表
			 */
      moveTo(source=[], select=[]) {
        source = JSON.parse(JSON.stringify(source));
        let moveToListArr = [];
        source = source.filter(item => {
          let list = select.filter(i => {
            return item.value === i.value
          });
          if (list.length > 0) moveToListArr.push(item);
          return list.length === 0;
        });
        return {
          newSource: this.$xdHelper.cloneDeep(source),
          moveTo: this.$xdHelper.cloneDeep(moveToListArr)
				}
      },

      /**
       * @description 给列表数组中添加指定数组数据并返回可添加的数据列表
       * @param source {Array} 原始数组
       * @param add {Array|any} 指定添加的数据数组
       * @return {Array}
       */
			addTo(source=[], add=[]){
        let ableAddList = [];
        source = JSON.parse(JSON.stringify(source));
        add.map(item=>{
          let list = source.filter(i => {
            return item.value === i.value
          });
          if(list.length ===0) ableAddList.push(item)
				});
				return ableAddList;
			},


      /**
			 * @description 需要校验检查参数是正确处理方法
       */
			checkParams(){
   			return this.rightSourceOrgData;
			},

			/**
			 * @description 数据改变事件
			 */
			change(){
			  this.$emit('onChange', this.checkParams())
			},

			/**
			 * 首次加载完成升级绑定数据
			 */
      firstUpdate() {
        if (this.firstStatus && this.initStatus) {
          if(this.checkParams().length > 0) this.update()
        }
      },


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

		}
  }
</script>

<style scoped lang="scss">
	.name {
		height: 20px;
		line-height: 20px;
		width: 100%;
		white-space: nowrap;
		overflow: hidden;
		text-overflow: ellipsis;
	}
	.xd-new-transfer {
		display: flex;
		justify-content: space-between;
		align-items: center;
		box-shadow: 0 0 10px rgba(0,0,0,.2);
		border-radius: 5px;
		padding: 10px;
		box-sizing: border-box;
		min-width: 700px;
		margin-bottom: 10px;
		position: relative;

		&__source{
			min-height: 240px;
			min-width: 240px;
			position: relative;
      flex:1;

			&-count{
				position: absolute;
				right: 24px;
				top: 58px;
				z-index: 100;
				color: #999;
			}
			&-search {
				height: 46px;
				display: flex;
				justify-content: flex-start;
				align-items: center;
				padding-bottom: 10px;

				& > * {

					&:first-child{
						width: 150px;
						margin-right: 10px;
						flex: 1;
					}

					&:last-child {
						flex-shrink: 0;
					}
				}
			}

			&-pagination{
				height: 30px;
				display: flex;
				justify-content: center;
				padding-top: 10px;
			}
		}

		&__btn {
			flex-shrink: 0;
			padding: 0 20px;
		}

		&__selected {
			min-height: 240px;
			min-width: 240px;
			position: relative;
      flex:1;

			&-search {
				height: 46px;
				display: flex;
				justify-content: flex-start;
				align-items: center;
				padding-bottom: 10px;

				& > * {

					&:first-child {
						width: 150px;
						flex: 1;
					}
				}
			}

			&-count {
				position: absolute;
				right: 24px;
				top: 58px;
				z-index: 100;
				color: #999;
			}
		}

		&-loading {
			min-height: 496px;
		}

	}


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