<template>
  <slot />
</template>

<script setup lang="ts">
import { onMounted, onUpdated, provide, toRef, type Ref } from 'vue';
import { ArrayUtils } from '@imengyu/imengyu-utils';
import { useFieldChildValueInjector } from './FormContext';

export interface CheckBoxGroupProps {
  /**
   * 当前复选框组选中的项目
   */
  modelValue?: string[];
  /**
   * 是否禁用整组复选框，设置后会禁用全部复选框。
   * @default false
   */
  disabled?: boolean;
  /**
   * 是否支持多选。仅限制用户选择，通过代码设置值时，不受到此限制。
   * @default true
   */
  multiple?: boolean;
}
export interface CheckBoxGroupInterface {
  /**
   * 切换所有复选框
   * @param options 传 true 为选中，false 为取消选中，不传参为取反
   */
  toggleAll: (options?: boolean | undefined | CheckBoxGroupToggleOptions) => void;
}
export interface CheckBoxGroupToggleOptions {
  /**
   * 是否是选中
   * @required true
   */
  checked: boolean,
  /**
   * 是否跳过禁用的复选框
   * @required true
   */
  skipDisabled: boolean,
}
export interface CheckBoxGroupContextInfo {
  value: Ref<string[]>,
  disabled: Ref<boolean>,
  onValueChange: (name: string|undefined, v: boolean) => void;
  onAddItem: (name: string, disabled: boolean) => void;
}

const props = withDefaults(defineProps<CheckBoxGroupProps>(), {
  modelValue: () => [] ,
  disabled: false,
  multiple: true,
});

const {
  value,
  updateValue,
} = useFieldChildValueInjector(
  toRef(props, 'modelValue'), 
  (v) => emit('update:modelValue', v)
);

provide<CheckBoxGroupContextInfo>('checkBoxGroupContext', {
  value: value,
  disabled: toRef(props, 'disabled'),
  onValueChange,
  onAddItem: (name, disabled) => {
    allCheck.set(name, disabled);
  },
});

const emit = defineEmits([ 'update:modelValue' ]);

const allCheck = new Map<string, boolean>();

function onValueChange(name: string|undefined, checked: boolean) {
  if (checked && !props.multiple) {
    updateValue([name as string]);
    return;
  }
  const valueNew = (value.value || []).concat();
  if (checked)
    ArrayUtils.addOnce(valueNew, name as string);
  else
    ArrayUtils.remove(valueNew, name as string);
  updateValue(valueNew);
}
function toggleAll(options?: boolean|undefined|CheckBoxGroupToggleOptions) {
  const allCheckNames = Array.from(allCheck.keys());
  if (typeof options === 'undefined') {
    //反选
    const valueNew = allCheckNames.filter((i) => value ? !value.value.includes(i) : false);
    updateValue(valueNew);
  } else if (typeof options === 'boolean') {
    //选中/取消选中
    const valueNew = options === true ? allCheckNames.concat() : [];
    updateValue(valueNew);
  } else if (typeof options === 'object') {
    //根据参数，选择时跳过禁用的选项
    const valueNew = allCheckNames.filter((name) => {
      if (options.skipDisabled && allCheck.get(name))
        return value ? value.value.includes(name) : false;
      return options.checked;
    });
    updateValue(valueNew);
  }
}

defineOptions({
  options: {
    styleIsolation: "shared",
    virtualHost: true,
  }
})
defineExpose<CheckBoxGroupInterface>({
  toggleAll,
})
</script>