<template>
  <FixedVirtualList 
    v-if="virtual"
    :data="data"
    :dataKey="dataKey"
    :containerStyle="innerStyle"
    :itemSize="virtualItemHeight"
    :bufferSize="2"
    v-bind="$attrs"
  >
    <template #item="{ item, index }"> 
      <SimpleListItem
        :item="item"
        :index="index"
        :dataDisplayProp="dataDisplayProp"
        :colorProp="colorProp"
        :disabledProp="disabledProp"
        :showCheck="mode !== 'select'"
        :checked="checkedList.indexOf(item) >= 0"
        :overrideItem="Boolean($slots.itemContent)"
        @click="onItemPress(item, index)"
      >
        <template v-if="$slots.itemContent" #itemContent>
          <slot name="itemContent" :item="item" :index="index" />
        </template>
      </SimpleListItem>
    </template>
    <template #empty>
      <slot name="empty">
        <Empty :description="emptyText" />
      </slot>
    </template>
    <template #inner>
      <slot name="inner" />
    </template>
  </FixedVirtualList>
  <FlexCol v-else :innerStyle="innerStyle">
    <SimpleListItem
      v-for="(item, index) in data"
      :key="dataKey ? (item as Record<string, any>)[dataKey] : index"
      :item="item"
      :index="index"
      :dataDisplayProp="dataDisplayProp"
      :colorProp="colorProp"
      :disabledProp="disabledProp"
      :showCheck="mode !== 'select'"
      :checked="checkedList.indexOf(item) >= 0"
      :overrideItem="Boolean($slots.itemContent)"
      @click="onItemPress(item, index)"
    >
      <template v-if="$slots.itemContent" #itemContent>
        <slot name="itemContent" :item="item" :index="index" />
      </template>
    </SimpleListItem>
    <slot v-if="data.length == 0" name="empty">
      <Empty :description="emptyText" />
    </slot>
    <slot name="inner" />
  </FlexCol>
</template>

<script setup lang="ts" generic="T">
import { computed, nextTick, provide, ref, watch, type ComputedRef, type Ref } from 'vue';
import { useTheme, type TextStyle, type ViewStyle } from '../theme/ThemeDefine';
import { DynamicColor, DynamicSize, DynamicSize2, DynamicVar } from '../theme/ThemeTools';
import type { CheckBoxDefaultButtonProps } from '../form/CheckBoxDefaultButton.vue';
import FlexCol from '../layout/FlexCol.vue';
import Empty from '../feedback/Empty.vue';
import FixedVirtualList from './FixedVirtualList.vue';
import SimpleListItem from './SimpleListItem.vue';

export interface SimpleListProps<T> {
  /**
   * 是否使用虚拟列表
   * @default false
   */
  virtual?: boolean;
  /**
   * 虚拟列表条目高度px
   * @default 40
   */
  virtualItemHeight?: number;
  /**
   * 条目的自定义样式
   */
  itemStyle?: ViewStyle;
  /**
   * 条目文字的自定义样式
   */
  textStyle?: TextStyle;
  /**
   * 选中的条目的自定义样式
   */
  checkedItemStyle?: ViewStyle;
  /**
   * 选中的条目文字的自定义样式
   */
  checkedTextStyle?: TextStyle;
  /**
   * 空数据时显示的文字
   */
  emptyText?: string,
  /**
   * 源数据
   */
  data: T[],
  /**
   * 数据项的唯一键名，用于vue循环优化
   */
  dataKey?: string,
  /**
   * 显示数据的prop，如果为空，则尝试直接把数据当 string 显示。
   */
  dataDisplayProp?: string,
  /**
   * 控制数据条目颜色的字段名称，为空则使用默认颜色。
   */
  colorProp?: string,
  /**
   * 控制是否禁用数据条目的字段名称，为空则不禁用。
   */
  disabledProp?: string,
  /**
   * 列表的选择模式
   *
   * * select 点击选择模式
   * * single-check 单选选择模式，条目右边有选择框
   * * mulit-check 多选选择模式，条目右边有选择框
   * @default 'select'
   */
  mode?: 'select'|'single-check'|'mulit-check',
  /**
   * 当列表显示选择框时，选择框的自定义属性
   * @default {
   *   borderColor: 'border.cell',
   *   checkColor: 'white',
   *   color: 'primary',
   *   size: 20,
   *   iconSize: mode === 'single-check' ? 10 : 16,
   *   type: mode === 'single-check' ? 'radio' : 'icon',
   *   disabled: false,
   * }
   */
  checkProps?: CheckBoxDefaultButtonProps,
  /**
   * 当用使用选择框模式时，默认选中条目
   * @default []
   */
  checkedItems?: T[],

  innerStyle?: ViewStyle;
}
export interface SimpleListContext {
  itemStyle: ComputedRef<ViewStyle>;
  textStyle: ComputedRef<TextStyle>;
  checkedItemStyle: ComputedRef<ViewStyle>;
  checkedTextStyle: ComputedRef<TextStyle>;
  checkProps: ComputedRef<CheckBoxDefaultButtonProps>;
  pressedColor: ComputedRef<string>;
}

const props = withDefaults(defineProps<SimpleListProps<T>>(), {
  mode: 'select',
  virtual: false,
  virtualItemHeight: 40,
});
const emit = defineEmits([ 'itemClick', 'selectedItemChanged' ]);

const themeContext = useTheme();
const themeStyles = themeContext.useThemeStyles({
  item: {
    padding: DynamicSize2('SimpleListItemPaddingVertical', 'SimpleListItemPaddingHorizontal', 20, 35),
    fontSize: DynamicSize('SimpleListItemFontSize', 28),
    borderTopStyle: 'solid',
    borderTopWidth: DynamicSize('SimpleListItemBorderTopWidth', 0),
    borderTopColor: DynamicColor('SimpleListItemBorderColor', 'border.cell'),
    borderBottomStyle: 'solid',
    borderBottomWidth: DynamicSize('SimpleListItemBorderBottomWidth', 2),
    borderBottomColor: DynamicColor('SimpleListItemBorderColor', 'border.cell'),
    color: DynamicColor('SimpleListItemColor', 'text.content'),
    backgroundColor: DynamicColor('SimpleListItemBackgroundColor', 'white'),
    flexDirection: 'row',
  },
  itemText: {
    flex: 1,
    fontSize: DynamicSize('SimpleListItemTextFontSize', 28),
    fontWeight: DynamicSize('SimpleListItemTextFontWeight', 'normal'),
    color: DynamicColor('SimpleListItemTextColor', 'text.content'),
  },
  itemTextChecked: {
    fontSize: DynamicSize('SimpleListItemCheckedTextFontSize', 28),
    fontWeight: DynamicVar('SimpleListItemCheckedTextFontWeight', 'bold'),
    color: DynamicColor('SimpleListItemCheckedTextColor', 'primary'),
  },
});

const itemStyle = computed(() => ({
  ...themeStyles.item.value,
  ...props.itemStyle,
} as ViewStyle));
const textStyle = computed(() => ({
  ...themeStyles.itemText.value,
  ...props.textStyle,
} as ViewStyle));
const checkedItemStyle = computed(() => ({
  ...themeStyles.item.value,
  ...props.checkedItemStyle,
} as ViewStyle));
const checkedTextStyle = computed(() => ({
  ...themeStyles.itemText.value,
  ...themeStyles.itemTextChecked.value,
  ...props.checkedTextStyle,
} as ViewStyle));
const checkProps = computed(() => ({
  borderColor: 'border.cell',
  checkColor: 'white',
  color: 'primary',
  size: 40,
  iconSize: props.mode === 'single-check' ? 20 : 32,
  type: props.mode === 'single-check' ? 'radio' : 'icon',
  disabled: false,
  ...props.checkProps,
} as CheckBoxDefaultButtonProps));
const pressedColor = computed(() => {
  return themeContext.resolveThemeColor('SimpleListItemPressedColor', 'pressed.white')!;
});


provide<SimpleListContext>('SimpleListContext', {
  itemStyle,
  textStyle,
  checkedItemStyle,
  checkedTextStyle,
  checkProps,
  pressedColor,
});

const checkedList = ref(props.checkedItems || []) as Ref<T[]>;

watch(() => props.checkedItems, (val) => {
  checkedList.value = val || [];
});

function onItemPress(item: T, index: number) {
  if (props.mode === 'single-check') {
    checkedList.value = ([ item ]);
    emit('selectedItemChanged', [ item ]);
  } else if (props.mode === 'mulit-check') {
    checkedList.value = ((prev) => {
      let arr : any[];
      if (prev.indexOf(item) >= 0)
        arr = prev.filter(k => {
          if (props.dataKey)
            return (k as any)[props.dataKey] !== (item as any)[props.dataKey];
          return k !== item;
        });
      else
        arr = prev.concat([ item ]);

      nextTick(() => {
        emit('selectedItemChanged', arr);
        console.log('selectedItemChanged', arr);
        
      });
      return arr;
    })(checkedList.value);
  }
  emit('itemClick', item, index);
}
</script>