<template>
  <FlexRow 
    center 
    :innerStyle="{
      ...themeStyles.view.value, 
      ...innerStyle,
      background: theme.resolveThemeColor(inputBackgroundColor),
    }"
    :flexShrink="0"
    overflow="hidden"
  >
    <FlexRow 
      center 
      :innerStyle="{
        ...themeStyles.input.value, 
        ...containerStyle 
      }"
      :gap="20"
    >
      <slot name="leftIcon">
        <Icon 
          v-if="leftIcon"
          :icon="leftIcon" 
          :size="leftIconSize"
          :color="leftIconColor"
          v-bind="leftIconProps"
       />
      </slot>
      <input
        :style="{
          ...themeStyles.inputInner.value, 
          ...inputStyle, 
          color: theme.resolveThemeColor(inputColor) 
        }"
        :value="valueTemp"
        :placeholder="placeholder"
        :placeholder-style="`color: ${theme.resolveThemeColor(placeholderTextColor)}`"
        type="text"
        confirm-type="search"
        @input="onInput"
        @focus="onFocus"
        @blur="onBlur"
        @confirm="onSumit"
      />
      <slot name="rightIcon" />
    </FlexRow>
    <slot 
      v-if="(
        cancelState === 'show' || 
        (inputFocus && (cancelState === 'show-active' || cancelState === 'show-active-or-no-empty')) || 
        (valueTemp !== '' && (cancelState === 'show-no-empty' || cancelState === 'show-active-or-no-empty'))
      )"
      name="cancelButton"
    >
      <Button 
        type="text"
        size="small"
        :text="cancelText"
        :textStyle="{
          color: theme.resolveThemeColor(cancelTextColor),
          ...cancelTextStyle
        }"
        :innerStyle="{ ...themeStyles.cancel.value, ...cancelStyle }"
        @click="onCancelPressed"
      />
    </slot>
    <slot
      v-if="(
        searchState === 'show' || 
        (inputFocus && (searchState === 'show-active' || searchState === 'show-active-or-no-empty')) || 
        (valueTemp !== '' && (searchState === 'show-no-empty' || searchState === 'show-active-or-no-empty'))
      )"
      name="searchButton" 
      :onSearchButtonClick="onSearchButtonClick"
    >
      <IconButton
        :icon="searchIcon"
        :size="searchIconSize"
        :color="searchIconColor"
        v-bind="searchIconProps"
        @click="onSearchButtonClick"
      />
    </slot>
    <slot name="rightButton" :onCustomButtonClick="onCustomButtonClick"/>
  </FlexRow>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';
import type { IconProps } from '../basic/Icon.vue';
import { type ViewStyle, type TextStyle, useTheme, propGetThemeVar } from '../theme/ThemeDefine';
import FlexRow from '../layout/FlexRow.vue';
import Button from '../basic/Button.vue';
import { DynamicSize } from '../theme/ThemeTools';
import Icon from '../basic/Icon.vue';
import IconButton from '../basic/IconButton.vue';

export interface SearchBarProp {
  /**
   * 输入框初始值
   */
  modelValue?: string;
  /**
   * 输入框的文字颜色
   * @default text.content
   */
  inputColor?: string;
  /**
   * 输入框的背景颜色
   * @default white
   */
  inputBackgroundColor?: string;
  /**
   * 输入框的placeholder
   */
  placeholder?: string;
  /**
   * 输入框的placeholderTextColor
   * @default text.second
   */
  placeholderTextColor?: string;
  /**
   * 取消按钮的文字
   * @default '取消'
   */
  cancelText?: string;
  /**
   * 取消按钮的文字颜色
   * @default primary
   */
  cancelTextColor?: string;
  /**
   * 点击取消按钮是否自动让输入框失去焦点
   * @default true
   */
  cancalLostFocus?: boolean;
  /**
   * 点击取消按钮是否自动清空输入框
   * @default true
   */
  cancalClear?: boolean;
  /**
   * 左侧图标
   * @default 'search'
   */
  leftIcon?: string|null;
  leftIconSize?: string|number;
  leftIconColor?: string;
  /**
   * 图标自定义属性
   */
  leftIconProps?: Partial<IconProps>;
  /**
   * 取消按钮显示
   * * hidden 不显示
   * * show 一直显示
   * * show-active 当输入框激活时显示
   * * show-no-empty 当输入框有文字时显示
   * * show-active-or-no-empty 当输入框激活或者有文字时显示
   * @default 'show-active-or-no-empty'
   */
  cancelState?: 'hidden'|'show'|'show-active'|'show-no-empty'|'show-active-or-no-empty';
  /**
   * 搜索按钮显示
   * * hidden 不显示
   * * show 一直显示
   * * show-active 当输入框激活时显示
   * * show-no-empty 当输入框有文字时显示
   * * show-active-or-no-empty 当输入框激活或者有文字时显示
   * @default 'hidden'
   */
  searchState?: 'hidden'|'show'|'show-active'|'show-no-empty'|'show-active-or-no-empty';
  /**
   * 搜索按钮图标
   * @default 'search'
   */
  searchIcon?: string;
  /**
   * 搜索按钮图标大小
   * @default 40
   */
  searchIconSize?: string|number;
  /**
   * 搜索按钮图标颜色
   * @default text.content
   */
  searchIconColor?: string;
  /**
   * 图标自定义属性
   */
  searchIconProps?: Partial<IconProps>;
  /**
   * 自定义样式
   */
  innerStyle?: ViewStyle;
  /**
   * 容器自定义样式
   */
  containerStyle?: ViewStyle;
  /**
   * 自定义样式
   */
  inputStyle?: TextStyle;
  /**
   * 自定义样式
   */
  cancelStyle?: ViewStyle;
  /**
   * 自定义样式
   */
  cancelTextStyle?: TextStyle;
}

const emit = defineEmits([ 'search', 'update:modelValue', 'blur', 'focus', 'cancel' ])

const theme = useTheme();

const props = withDefaults(defineProps<SearchBarProp>(), {
  inputColor: () => propGetThemeVar('SearchBarTextColor', 'text.content'),
  inputBackgroundColor: () => propGetThemeVar('SearchBarBackgroundColor', 'white'),
  searchState: 'hidden',
  searchIcon: () => propGetThemeVar('SearchBarSearchIcon', 'search'),
  searchIconSize: () => propGetThemeVar('SearchBarSearchIconSize', 40),
  searchIconColor: () => propGetThemeVar('SearchBarSearchIconColor', 'text.content'),
  placeholder: '',
  placeholderTextColor: () => propGetThemeVar('SearchBarCancelTextColor', 'text.second'),
  cancelText: '取消',
  cancelTextColor: () => propGetThemeVar('SearchBarCancelTextColor', 'primary'),
  cancalLostFocus: true,
  cancalClear: true,
  leftIcon: () => propGetThemeVar('SearchBarLeftIcon', 'search'),
  leftIconSize: () => propGetThemeVar('SearchBarLeftIconSize', 40),
  leftIconColor: () => propGetThemeVar('SearchBarLeftIconColor', 'text.content'),
  cancelState: 'show-active-or-no-empty',
});

const valueTemp = ref(props.modelValue ?? '');

watch(() => props.modelValue, () => {
  valueTemp.value = props.modelValue ?? '';
});
function updateValue(v: string) {
  valueTemp.value = v;
  emit('update:modelValue', v);
}

const themeStyles = theme.useThemeStyles({
  view: {
    position: 'relative',
    borderRadius: DynamicSize('SearchBarBorderRadius', 40),
    paddingHorizontal: DynamicSize('SearchBarPaddingHorizontal', 28),
    paddingVertical: DynamicSize('SearchBarPaddingVertical', 16),
  },
  input: {
    flex: 1,
    position: 'relative',
  },
  inputInner: {
    flex: 1,
    paddingHorizontal: DynamicSize('SearchBarCancelPaddingHorizontal', 20),
    paddingVertical: DynamicSize('SearchBarCancelPaddingVertical', 16),
  },
  cancel: {
    paddingTop: DynamicSize('SearchBarCancelPaddingVertical', 0),
    paddingBottom: DynamicSize('SearchBarCancelPaddingVertical', 0),
    paddingHorizontal: DynamicSize('SearchBarCancelPaddingHorizontal', 20),
  },
});

const inputFocus = ref(false);

function onInput(e: any) {
  inputFocus.value = true;
  updateValue(e.detail.value);
}
function onFocus() {
  inputFocus.value = true;
  emit('focus');
}
function onBlur() {
  inputFocus.value = false;
  emit('blur');
}
function onCancelPressed() {
  if (props.cancalLostFocus)
    uni.hideKeyboard()
  if (props.cancalClear)
    updateValue('');
  emit('cancel');
}
function onSearchButtonClick() {
  emit('search', valueTemp.value);
  uni.hideKeyboard()
}
function onSumit() {
  emit('search', valueTemp.value);
  uni.hideKeyboard()
}
function onCustomButtonClick(type: 'search'|'cancel') {
  if (type === 'search') onSumit();
  else if (type === 'cancel') onCancelPressed();
}
</script>