/***********************************************
 * @Author: shiyzhang zsyou0911@126.com
 * @Date: 2024-03-01 14:40
 * @Description: useTabMixin.ts
 *
 ***********************************************/
// 主要用于日和星期的互斥使用
import { computed, inject, reactive, ref, unref, watch } from 'vue';
import { propTypes } from '../../_utils/propTypes';

export enum TypeEnum {
  unset = 'UNSET',
  every = 'EVERY',
  range = 'RANGE',
  loop = 'LOOP',
  work = 'WORK',
  last = 'LAST',
  specify = 'SPECIFY',
}

// use 公共 props
export function useTabProps(options) {
  const defaultValue = options?.defaultValue ?? '?';
  return {
    value: propTypes.string.def(defaultValue),
    disabled: propTypes.bool.def(false),
    ...options?.props,
  };
}

// use 公共 emits
export function useTabEmits() {
  return ['change', 'update:value'];
}

// use 公共 setup
export function useTabSetup(props, context, options) {
  const { emit } = context;
  const prefixCls = inject('prefixCls');
  const defaultValue = ref(options?.defaultValue ?? '?');
  // 类型
  const type = ref(options.defaultType ?? TypeEnum.every);
  const valueList = ref<any[]>([]);
  // 对于不同的类型，所定义的值也有所不同
  const valueRange = reactive(options.valueRange);
  const valueLoop = reactive(options.valueLoop);
  const valueWeek = reactive(options.valueWeek);
  const valueWork = ref(options.valueWork);
  const maxValue = ref(options.maxValue);
  const minValue = ref(options.minValue);

  // 根据不同的类型计算出的value
  const computeValue = computed(() => {
    const valueArray: any[] = [];
    switch (type.value) {
      case TypeEnum.unset:
        valueArray.push('?');
        break;
      case TypeEnum.every:
        valueArray.push('*');
        break;
      case TypeEnum.range:
        valueArray.push(`${valueRange.start}-${valueRange.end}`);
        break;
      case TypeEnum.loop:
        valueArray.push(`${valueLoop.start}/${valueLoop.interval}`);
        break;
      case TypeEnum.work:
        valueArray.push(`${valueWork.value}W`);
        break;
      case TypeEnum.last:
        valueArray.push('L');
        break;
      case TypeEnum.specify:
        if (valueList.value.length === 0) {
          valueList.value.push(minValue.value);
        }
        valueArray.push(valueList.value.join(','));
        break;
      default:
        valueArray.push(defaultValue.value);
        break;
    }
    return valueArray.length > 0 ? valueArray.join('') : defaultValue.value;
  });
  // 指定值范围区间，介于最小值和最大值之间
  const specifyRange = computed(() => {
    const range: number[] = [];
    if (maxValue.value != null) {
      for (let i = minValue.value; i <= maxValue.value; i++) {
        range.push(i);
      }
    }
    return range;
  });

  watch(
    () => props.value,
    (val) => {
      if (val !== computeValue.value) {
        parseValue(val);
      }
    },
    { immediate: true },
  );

  watch(computeValue, (v) => updateValue(v));

  function updateValue(value) {
    emit('change', value);
    emit('update:value', value);
  }

  /**
   * parseValue
   * @param value
   */
  function parseValue(value) {
    if (value === computeValue.value) {
      return;
    }
    try {
      if (!value || value === defaultValue.value) {
        type.value = TypeEnum.every;
      } else if (value.indexOf('?') >= 0) {
        type.value = TypeEnum.unset;
      } else if (value.indexOf('-') >= 0) {
        type.value = TypeEnum.range;
        const values = value.split('-');
        if (values.length >= 2) {
          valueRange.start = parseInt(values[0]);
          valueRange.end = parseInt(values[1]);
        }
      } else if (value.indexOf('/') >= 0) {
        type.value = TypeEnum.loop;
        const values = value.split('/');
        if (values.length >= 2) {
          valueLoop.start = value[0] === '*' ? 0 : parseInt(values[0]);
          valueLoop.interval = parseInt(values[1]);
        }
      } else if (value.indexOf('W') >= 0) {
        type.value = TypeEnum.work;
        const values = value.split('W');
        if (!values[0] && !isNaN(values[0])) {
          valueWork.value = parseInt(values[0]);
        }
      } else if (value.indexOf('L') >= 0) {
        type.value = TypeEnum.last;
      } else if (value.indexOf(',') >= 0 || !isNaN(value)) {
        type.value = TypeEnum.specify;
        valueList.value = value.split(',').map((item) => parseInt(item));
      } else {
        type.value = TypeEnum.every;
      }
    } catch (e) {
      type.value = TypeEnum.every;
    }
  }

  const beforeRadioAttrs = computed(() => ({
    class: ['choice'],
    disabled: props.disabled || unref(options.disabled),
  }));
  const inputNumberAttrs = computed(() => ({
    class: ['w60'],
    max: maxValue.value,
    min: minValue.value,
    precision: 0,
  }));
  const typeRangeAttrs = computed(() => ({
    disabled: type.value !== TypeEnum.range || props.disabled || unref(options.disabled),
    ...inputNumberAttrs.value,
  }));
  const typeLoopAttrs = computed(() => ({
    disabled: type.value !== TypeEnum.loop || props.disabled || unref(options.disabled),
    ...inputNumberAttrs.value,
  }));
  const typeSpecifyAttrs = computed(() => ({
    disabled: type.value !== TypeEnum.specify || props.disabled || unref(options.disabled),
    class: ['list-check-item'],
  }));

  return {
    type,
    TypeEnum,
    prefixCls,
    defaultValue,
    valueRange,
    valueLoop,
    valueWeek,
    valueList,
    valueWork,
    maxValue,
    minValue,
    computeValue,
    specifyRange,
    updateValue,
    parseValue,
    beforeRadioAttrs,
    inputNumberAttrs,
    typeRangeAttrs,
    typeLoopAttrs,
    typeSpecifyAttrs,
  };
}
