<template>
  <Touchable 
    touchable 
    overflow="hidden"
    :width="isListStyle ? undefined : itemSize.width"
    :height="isListStyle ? undefined : itemSize.height"
    :innerStyle="{
      ...(isListStyle ? themeStyles.itemListStyle.value : themeStyles.item.value), 
      ...(isListStyle ? selectStyleType(item.state, 'notstart', {
        notstart: {},
        uploading: themeStyles.itemListStyleUploading.value,
        success: themeStyles.itemListStyleSuccess.value,
        fail: themeStyles.itemListStyleFail.value,
      }) : {}), 
      ...props.style as ViewStyle,
    }"
    :direction="isListStyle ? 'row' : 'column'"
    center
    @click="emit('click')" 
  >
    <template v-if="!isListStyle">
      <IconButton 
        v-if="showDelete"
        icon="delete-filling"
        color="danger"
        :buttonStyle="themeStyles.itemDeleteButton.value"
        @click.stop="emit('delete')" />
        
      <FlexView v-if="item.state === 'uploading'" :innerStyle="{
        ...itemMaskStyle,
        backgroundColor: themeContext.resolveThemeColor('UploaderListItemUploadingBackgroundColor', 'mask.primary'),
      }">
        <ActivityIndicator :color="itemMaskTextColor" :size="loadingSize" />
        <Text :color="itemMaskTextColor" :style="itemMaskTextStyle" textAlign="center" :text="item.message" />
      </FlexView>
      <FlexView v-if="item.state === 'fail'" :innerStyle="{
        ...itemMaskStyle,
        backgroundColor: themeContext.resolveThemeColor('UploaderListItemUploadingBackgroundColor', 'mask.danger'),
      }">
        <Icon icon="error" :color="itemMaskTextColor" :size="iconSize" />
        <Text :color="itemMaskTextColor" :style="itemMaskTextStyle" textAlign="center" :text="item.message" />
      </FlexView>
    </template>

    <Image
      v-if="isImage"
      :src="item.previewPath || item.filePath" 
      :defaultImage="defaultSource ?? fileIcon" 
      :width="isListStyle ? itemListStyleImageSize : itemSize.width"
      :height="isListStyle ? itemListStyleImageSize : itemSize.height"
      :innerStyle="{ 
        ...(isListStyle ? themeStyles.itemListStyleImage.value : themeStyles.itemImage.value), 
        ...imageStyle,
      }" 
      mode="aspectFill" 
    />
    <Icon v-else :icon="fileIcon" :color="itemMaskTextColor" :size="itemListStyleImageSize" />

    <FlexRow v-if="isListStyle" :flex="1" align="center">
      <Width :size="20" />
      <FlexCol :flex="1">
        <Text :fontSize="26" :text="StringUtils.path.getFileName(item.filePath)" />
        <Text :fontSize="22" :text="item.message" />
        <Height :size="10" /> 
        <Progress :progressColor="selectStyleType(item.state, 'notstart', {
          notstart: 'primary',
          uploading: 'primary',
          success: 'success',
          fail: 'danger',
        })" :value="item.progress || 0" />
      </FlexCol>
      <Icon v-if="item.state === 'success'" icon="select-bold" color="success" />
      <Icon v-else-if="item.state === 'fail'" icon="close-bold" color="danger" />
      <ActivityIndicator v-else-if="item.state === 'uploading'" :size="45" />
      <Width :size="20" />
      <IconButton v-if="showDelete" icon="trash" @click.stop="emit('delete')" />
    </FlexRow>
  </Touchable>
</template>

<script setup lang="ts">
import { computed, watch } from 'vue';
import { useTheme, type TextStyle, type ViewStyle } from '../theme/ThemeDefine';
import { DynamicColor, DynamicSize, DynamicSize2, selectStyleType } from '../theme/ThemeTools';
import { StringUtils } from '@imengyu/imengyu-utils';
import ActivityIndicator from '../basic/ActivityIndicator.vue';
import Icon from '../basic/Icon.vue';
import IconButton from '../basic/IconButton.vue';
import Image from '../basic/Image.vue';
import Text from '../basic/Text.vue';
import FlexCol from '../layout/FlexCol.vue';
import FlexView from '../layout/FlexView.vue';
import FlexRow from '../layout/FlexRow.vue';
import Progress from '../display/Progress.vue';
import IconApk from '../images/files/apk.png';
import IconAudio from '../images/files/audio.png';
import IconDefault from '../images/files/default.png';
import IconExcel from '../images/files/excel.png';
import IconPowerpoint from '../images/files/powerpoint.png';
import IconUnknown from '../images/files/unknown.png';
import IconVideo from '../images/files/video.png';
import IconWord from '../images/files/word.png';
import IconZip from '../images/files/zip.png';
import IconPdf from '../images/files/pdf.png';
import Width from '../layout/space/Width.vue';
import Height from '../layout/space/Height.vue';
import Touchable from '../feedback/Touchable.vue';
import type { UploaderItem } from './Uploader';

export interface UploaderListItemProps {
  item: UploaderItem;
  style?: ViewStyle;
  imageStyle?: ViewStyle;
  itemMaskTextStyle?: TextStyle;
  itemMaskStyle?: ViewStyle;
  itemSize: { width: number, height: number };
  showDelete: boolean;
  defaultSource: string | undefined;
  isListStyle: boolean;
}

const props = defineProps<UploaderListItemProps>();
const emit = defineEmits(['click', 'delete'])
const themeContext = useTheme();

const itemListStyleImageSize = computed(() => themeContext.resolveThemeSize('UploaderListItemListImageSize', 64));

const themeStyles = themeContext.useThemeStyles({
  item: {
    position: 'relative',
    borderRadius: DynamicSize('UploaderListItemBorderRadius', 20),
    backgroundColor: DynamicColor('UploaderListItemBackgroundColor', 'grey'),
    marginHorizontal: DynamicSize('UploaderListItemGridMargin', 4),
    marginBottom: DynamicSize('UploaderListItemGridMargin', 4),
  },
  itemListStyle: {
    position: 'relative',
    borderStyle: 'solid',
    borderWidth: DynamicSize('UploaderListItemListBorderWidth', 2),
    borderRadius: DynamicSize('UploaderListItemBorderRadius', 15),
    backgroundColor: DynamicColor('UploaderListItemBackgroundColor', 'white'),
    padding: DynamicSize2('UploaderListItemListPaddingVertical', 'UploaderListItemListPaddingHorizontal', 20, 20),
    marginBottom: DynamicSize('UploaderListItemListMargin', 10),
  },
  itemListStyleUploading: {
    borderColor: DynamicColor('UploaderListItemListUploadingBorderColor', 'primary'),
    backgroundColor: DynamicColor('UploaderListItemListUploadingBackgroundColor', 'background.primary'),
  },
  itemListStyleSuccess: {
    borderColor: DynamicColor('UploaderListItemListSuccessBorderColor', 'success'),
    backgroundColor: DynamicColor('UploaderListItemListSuccessBackgroundColor', 'background.success'),
  },
  itemListStyleFail: {
    borderColor: DynamicColor('UploaderListItemListFailBorderColor', 'danger'),
    backgroundColor: DynamicColor('UploaderListItemListFailBackgroundColor', 'background.danger'),
  },
  itemListStyleImage: {
    borderRadius: DynamicSize('UploaderListItemListBorderRadius', 20),
  },
  itemImage: {
    position: 'absolute',
    top: 0,
    left: 0,
    borderRadius: DynamicSize('UploaderListItemGridBorderRadius', 15),
    zIndex: 5,
  },
  itemList: {
  },
  itemMask: {
    backgroundColor: 'rgba(0,0,0,0.3)',
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: DynamicSize('UploaderListItemGridBorderRadius', 20),
    zIndex: 10,
  },
  itemMaskText: {
    marginTop: 5,
    color: '#fff',
  },
  itemDeleteButton: {
    position: 'absolute',
    right: 0,
    top: 0,
    zIndex: 30,
    borderRadius: DynamicSize('UploaderListItemGridBorderRadius', 20),
    backgroundColor: '#fff',
  },
});

const itemMaskTextStyle = computed(() => ({ ...themeStyles.itemMaskText.value, ...props.itemMaskTextStyle }));
const itemMaskStyle = computed(() => ({ ...themeStyles.itemMask.value, ...props.itemMaskStyle }));
const itemMaskTextColor = computed(() => props.itemMaskTextStyle?.color || themeStyles.itemMaskText.value.color as string);
const iconSize = computed(() => themeContext.resolveThemeSize('UploaderListItemIconSize', 65));
const loadingSize = computed(() => themeContext.resolveThemeSize('UploaderListItemLoadingSize', 35));

const imageExts = [ 'jpg', 'jpeg', 'png', 'webp', 'gif' ]
const isImage = computed(() => {
  return props.item.isImage 
    || (props.item.previewPath && imageExts.includes(StringUtils.path.getFileExt(props.item.previewPath)))
    || (props.item.filePath && imageExts.includes(StringUtils.path.getFileExt(props.item.filePath || ''))
  )
});

const fileIcon = computed(() => {
  const ext = StringUtils.path.getFileExt(props.item.filePath || '');
  switch (ext) {
    case 'apk1':
    case 'apk': return IconApk;
    case 'audio': 
    case 'mp3': 
    case 'wav': 
    case 'wma': 
    case 'ogg': 
    case 'flac':
      return IconAudio;
    case 'default': 
      return IconDefault;
    case 'excel': 
    case 'xls': 
    case 'xlsx': 
      return IconExcel;
    case 'powerpoint': 
    case 'ppt': 
    case 'pptx': 
      return IconPowerpoint;
    case 'unknown': 
    case 'video': 
    case 'mp4': 
    case 'mov': 
    case 'wmv': 
    case 'avi': 
    case 'flv': 
      return IconVideo;
    case 'word': 
    case 'docx': 
    case 'doc': 
    case 'txt': 
    case 'rtf': 
      return IconWord;
    case 'zip': 
    case '7z': 
    case 'rar': 
      return IconZip;
    case 'pdf': 
      return IconPdf;
  }
  return IconUnknown;
});
</script>