<template>
  <div v-if="!hide" class="es-checkbox-group">
    <div
      v-if="readonly"
      class="es-input__inner"
      :class="{ 'es-plain': this.plain || $attrs.text }"
    >
      {{ labelVal }}
    </div>
    <el-checkbox-group
      v-else
      v-show="display"
      v-model="model"
      v-bind="{ valueKey: valKey, labelKey: label, ...$attrs }"
      v-on="$listeners"
    >
      <template v-if="genre === 'button'">
        <el-checkbox-button
          v-for="(item, index) in results"
          :key="index"
          v-bind="getprops($attrs, item)"
          :label="isObject || typeof item == 'string' ? item : item[valKey]"
          :disabled="typeof item == 'string' ? false : item.disabled"
        >
          {{
            typeof item == 'string'
              ? item
              : item[label]
              ? item[label]
              : item.label || item[valKey]
          }}
        </el-checkbox-button>
      </template>
      <template v-else>
        <el-checkbox
          v-for="(item, index) in results"
          :key="index"
          v-bind="getprops($attrs, item)"
          :label="isObject || typeof item == 'string' ? item : item[valKey]"
          :disabled="typeof item == 'string' ? false : item.disabled"
          :border="genre === 'border'"
        >
          {{
            typeof item == 'string'
              ? item
              : item[label]
              ? item[label]
              : item.label || item[valKey]
          }}
        </el-checkbox>
      </template>
    </el-checkbox-group>
  </div>
</template>

<script>
import { findSysCode, getDictList } from 'eoss-ui/src/config/api.js';
import { debounce } from 'throttle-debounce';
import store from 'eoss-ui/src/utils/store';
import util from 'eoss-ui/src/utils/util';
export default {
  name: 'EsCheckboxGroup',
  inheritAttrs: false,
  inject: {
    esForm: {
      default: ''
    }
  },
  props: {
    method: {
      type: String,
      default: 'get'
    },
    service: String,
    // 	选择项本地数据
    data: {
      type: Array,
      default() {
        return [];
      }
    },
    param: {
      type: Object,
      default() {
        return {};
      }
    },
    // 选择项远程地址
    url: String,
    hide: {
      type: Boolean,
      default: false
    },
    // 选择项获取代码表数据(优先级大于url)
    sysCode: String,
    // 	样式风格 button(按钮样式), border(带有边框)
    genre: {
      type: String,
      default: ''
    },
    separator: {
      type: String,
      default: '、'
    },
    display: {
      type: Boolean,
      default: true
    },
    valueType: {
      type: String,
      default: 'string',
      validator: function (value) {
        return ['string', 'object'].includes(value);
      }
    },
    valueKey: {
      type: String,
      default: 'value'
    },
    // 指定选择项显示值的键名，data元素是对象类型时必填
    labelKey: {
      type: String,
      default: 'name'
    },
    value: [Array, String],
    readonly: Boolean,
    plain: Boolean,
    ajax: {
      type: Boolean,
      default: true
    },
    isNoParamRequest: {
      type: Boolean,
      default: true
    },
    dataKey: String
  },
  data() {
    return {
      options: '',
      canceled: false
    };
  },
  computed: {
    isObject() {
      if (
        this.value !== '' &&
        Array.isArray(this.value) &&
        this.value.length > 0 &&
        util.isObject(this.value[0])
      ) {
        return true;
      } else {
        if (this.valueType === 'object') {
          return true;
        } else {
          return false;
        }
      }
    },
    model: {
      get() {
        return this.value === undefined ? [] : this.value;
      },
      set(val) {
        return val;
      }
    },
    label() {
      if (this.sysCode) {
        return this.service ? 'label' : 'shortName';
      }
      return this.labelKey;
    },
    valKey() {
      if (this.sysCode) {
        return this.service ? 'value' : 'cciValue';
      }
      return this.valueKey;
    },
    results() {
      return this.options ? this.options : this.data;
    },
    labelVal() {
      let model =
        typeof this.model === 'string'
          ? this.model.split(',')
          : this.model || [];
      let label = model.map((item) => {
        if (util.isObject(item)) {
          return item[this.label];
        }
        if (util.isObject(this.results[0])) {
          let vals = [];
          this.results.forEach((ele) => {
            if (ele[this.valKey] === item) {
              vals.push(ele[this.label]);
            }
          });
          return vals.join(this.separator);
        }
        return item;
      });
      return label.join(this.separator);
    },
    findCode() {
      if (this.service) {
        return `/${this.service}${getDictList}`;
      }
      return findSysCode;
    }
  },
  watch: {
    sysCode: {
      immediate: true,
      handler(val, old) {
        if (val && val != old) {
          const options = store.get(val);
          if (options) {
            this.options = JSON.parse(JSON.stringify(options));
          } else {
            this.getData(this.findCode, val);
          }
        }
      }
    },
    url: {
      immediate: true,
      handler(val) {
        if (val && !this.sysCode) {
          this.getData(val);
        }
      }
    },
    param: {
      deep: true,
      handler() {
        this.url && this.getData(this.url);
      }
    }
  },
  beforeCreate() {
    this.getData = debounce(500, (url, sysCode) => {
      this.getDatas(url, sysCode);
    });
  },
  created() {
    this.bindEventBus();
  },
  mounted() {},
  methods: {
    getDatas(url, sysCode) {
      let params = {};
      if (this.results.length === 0) {
        params = util.extend(
          {},
          this.param,
          sysCode ? { sysAppCode: sysCode, code: sysCode } : {}
        );
      } else {
        return false;
      }
      if (
        !this.ajax ||
        (!this.isNoParamRequest && Object.keys(this.param).length == 0)
      ) {
        return false;
      }
      this.loading = true;
      util
        .ajax({
          url: url,
          method: this.method,
          params: params,
          data: params
        })
        .then((res) => {
          this.loading = false;
          this.canceled = false;
          if (res.rCode === 0) {
            this.options = JSON.parse(JSON.stringify(res.results));
            if (sysCode || this.dataKey) {
              const bus = this.bus || this.$root.Bus;
              bus &&
                bus.$emit(
                  sysCode || this.dataKey,
                  JSON.parse(JSON.stringify(this.options))
                );
              store.set(sysCode, JSON.parse(JSON.stringify(res.results)));
            }
          } else {
            let msg = res.msg || '系统错误，请联系管理员！';
            this.$message.error(msg);
          }
        })
        .catch((err) => {
          this.loading = false;
          if (err.message) {
            if (err.message !== 'canceled') {
              this.$message.error(err.message);
            }
            if (err.message === 'canceled' && sysCode) {
              this.canceled = true;
            }
          }
        });
    },
    getprops(attrs, res) {
      if (res.checked && this.model) {
        this.$emit(
          'input',
          this.valueType === 'object' ? res : res[this.valKey]
        );
      }
      return util.isObject(res) ? { ...attrs, ...res } : attrs;
    },
    setOptions(val) {
      this.options = val;
    },
    bindEventBus() {
      const bus = this.bus || this.$root.Bus;
      bus && bus.$on(this.sysCode || this.dataKey, this.setOptions);
    },
    unbindEventBus() {
      const bus = this.bus || this.$root.Bus;
      bus && bus.$off(this.sysCode || this.dataKey, this.setOptions);
    }
  },
  beforeDestroy() {
    this.unbindEventBus();
  }
};
</script>
