<template>
  <Touchable
    :touchable="!disabled"
    :activeOpacity="activeOpacity"
    :innerStyle="{ 
      ...(block ? themeStyles.checkBoxFull.value : themeStyles.checkBox.value), 
      ...innerStyle 
    }"
    innerClass="nana-check"
    center
    direction="row"
    @click.stop="switchOn"
  >
    <slot name="check" v-if="checkPosition === 'left'" icon="check" :on="value" :disabled="disabled" :shape="shape">
      <CheckBoxDefaultButton 
        :on="value"
        :disabled="disabled"
        :shape="shape"
        :size="checkSize"
        :checkedBackgroundColor="themeContext.resolveThemeColor(color)"
        :checkedBorderColor="themeContext.resolveThemeColor(color)"
        :borderColor="themeContext.resolveThemeColor(borderColor)"
        :checkColor="themeContext.resolveThemeColor(checkColor)"
        :icon="props.icon"
      />
    </slot>
    <slot>
      <FlexCol>
        <Text 
          :innerStyle="{
            ...themeStyles.checkText.value,
            ...textStyle,
            color: themeContext.resolveThemeColor(props.disabled === true ? disabledTextColor : textColor),
            display: StringUtils.isNullOrEmpty(text) ? 'none' : 'flex',
          }"
          :text="text" 
        />
        <slot name="extraText">
        </slot>
      </FlexCol>
    </slot>
    <slot name="check" v-if="checkPosition === 'right'" icon="check" :on="value" :disabled="disabled" :shape="shape">
      <CheckBoxDefaultButton 
        :on="value"
        :disabled="disabled"
        :shape="shape"
        :size="checkSize"
        :checkedBackgroundColor="themeContext.resolveThemeColor(color)"
        :checkedBorderColor="themeContext.resolveThemeColor(color)"
        :borderColor="themeContext.resolveThemeColor(borderColor)"
        :checkColor="themeContext.resolveThemeColor(checkColor)"
        :icon="props.icon"
      />
    </slot>
  </Touchable>
</template>

<script setup lang="ts">
import { computed, inject, onMounted, toRef, watch } from 'vue';
import { useCellContext } from '../basic/CellContext';
import { propGetThemeVar, useTheme, type TextStyle, type ViewStyle } from '../theme/ThemeDefine';
import { useFieldChildValueInjector } from './FormContext';
import { DynamicSize } from '../theme/ThemeTools';
import { StringUtils } from '@imengyu/imengyu-utils';
import type { CheckBoxGroupContextInfo } from './CheckBoxGroup.vue';
import CheckBoxDefaultButton from './CheckBoxDefaultButton.vue';
import Text from '../basic/Text.vue';
import Touchable from '../feedback/Touchable.vue';
import FlexCol from '../layout/FlexCol.vue';

export interface CheckBoxProps {
  /**
   * 是否选中复选框
   * @default false
   */
  modelValue?: boolean;
  /**
   * 当前复选框在复选框组中的value，不能与其他重复
   */
  name?: string;
  /**
   * 复选框的文字
   */
  text?: string;
  /**
   * 复选框的形状
   * @default 'square'
   */
  shape?: "square"|"round";
  /**
   * 复选框占满整个父元素，默认否
   * @default false
   */
  block?: boolean,
  /**
   * 复选框按钮位置，默认在左
   * @default 'left'
   */
  checkPosition?: "left"|"right";
  /**
   * 复选框未选择时的边框颜色
   * @default border.input
   */
  borderColor?: string|undefined;
  /**
   * 复选框选中时勾的颜色
   * @default white
   */
  checkColor?: string|undefined;
  /**
   * 复选框按钮大小，默认是 36
   * @default 36
   */
  checkSize?: number|undefined;
  /**
   * 按下时透明度
   * @default 0.75
   */
  activeOpacity?: number,
  /**
   * 复选框的颜色，默认是 primary
   * @default primary
   */
  color?: string;
  /**
   * 是否禁用复选框
   * @default false
   */
  disabled?: boolean;
  /**
   * 选择勾的图标
   * @default 'check-mark'
   */
  icon?: string;
  /**
   * 文字颜色
   * @default text.content
   */
  textColor?: string;
  /**
   * 禁用状态下文字颜色
   * @default text.second
   */
  disabledTextColor?: string;
  /**
   * 自定义文字样式
   */
  textStyle?: TextStyle;
  /**
   * 自定义样式
   */
  innerStyle?: ViewStyle;
}

const props = withDefaults(defineProps<CheckBoxProps>(), {
  modelValue: false,
  shape: () => propGetThemeVar('CheckBoxShape', 'square'),
  block: false,
  checkPosition: () => propGetThemeVar('CheckBoxCheckPosition', 'left'),
  borderColor: () => propGetThemeVar('CheckBoxBorderColor', 'border.input'),
  checkColor: () => propGetThemeVar('CheckBoxCheckColor', 'white'),
  textColor: () => propGetThemeVar('CheckBoxTextColor', 'text.content'),
  disabledTextColor: () => propGetThemeVar('CheckBoxDisabledTextColor', 'text.second'),
  color: () => propGetThemeVar('CheckBoxColor', 'primary'),
  checkSize: () => propGetThemeVar('CheckBoxCheckSize', 36),
  activeOpacity: () => propGetThemeVar('CheckBoxActiveOpacity', 0.75),
  disabled: false,
  icon: 'check-mark',
});

const emit = defineEmits<{
  (e: 'update:modelValue', value: boolean): void;
}>();

const themeContext = useTheme();
const themeStyles = themeContext.useThemeStyles({
  checkBox: {
    alignSelf: 'flex-start',
    marginHorizontal: DynamicSize('CheckBoxMarginHorizontal', 4),
  },
  checkBoxFull: {
    alignSelf: 'stretch',
    width: '100%',
    justifyContent: 'space-between',
    marginHorizontal: DynamicSize('CheckBoxMarginHorizontal', 4),
  },
  check: {
    alignSelf: 'flex-start',
    alignItems: 'center',
    justifyContent: 'center',
  },
  checkText: {
    fontSize: DynamicSize('CheckBoxTextFontSize', 28),
  },
});

const groupContext = inject<CheckBoxGroupContextInfo>('checkBoxGroupContext', null as any);
const cellContext = useCellContext();
const disabled = computed(() => props.disabled === true || groupContext?.disabled.value);


watch(() => [ props.name, props.disabled ], () => {
  if (props.name)
    groupContext?.onAddItem(props.name, props.disabled);
}, { immediate: true })

const {
  value,
  updateValue,
} = useFieldChildValueInjector(
  toRef(props, 'modelValue'), 
  (v) => emit('update:modelValue', v),
  groupContext ? {
    getValue: () => groupContext!.value.value && groupContext.value.value.indexOf(props.name ?? '') >= 0,
    updateValue: (v) => groupContext!.onValueChange(props.name, !value.value),
  } : undefined,
);

function switchOn() {
  if (props.disabled)
    return;
  updateValue(!value.value);
}

onMounted(() => {
  if (cellContext)
    cellContext.setOnClickListener(() => switchOn());
})

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