<template>
  <Touchable
    :innerStyle="{
      ...currentStyle.style,
      ...innerStyle,
    }"
    :innerClass="['nana-button', props.block ? 'nana-button-block' : 'nana-button-auto']"
    center
    direction="row"
    v-bind="viewProps"
    :pressedColor="finalPressedColor"
    :touchable="touchable && !loading"
    :gap="iconMargin"
    @state="(v) => state = v"
    @click="(e) => emit('click', e)"
  >
    <slot name="leftIcon">
      <ActivityIndicator 
        v-if="loading"
        :size="selectStyleType(size, 'medium', FonstSizes)"
        :color="themeContext.resolveThemeColor(loadingColor) || currentStyle.color"
      />
      <Icon
        v-else-if="icon"
        :icon="icon"
        :size="selectStyleType(size, 'medium', FonstSizes)"
        :color="currentStyle.color"
        v-bind="iconProps"
      />
    </slot>
    <slot>
      <Text 
        :color="textColorFinal" 
        :fontSize="selectStyleType(size, 'medium', FonstSizes)" 
        :fontWeight="type === 'text' ? 'bold' : undefined"
        :innerStyle="textStyle"
        :text="currentText"
        v-bind="textProps"
      />
    </slot>
    <slot name="rightIcon">
      <Icon
        v-if="rightIcon"
        :icon="rightIcon"
        :size="selectStyleType(size, 'medium', FonstSizes)"
        :color="currentStyle.color"
        v-bind="rightIconProps"
      />
    </slot>
  </Touchable>
</template>

<script setup lang="ts">
import { computed, inject, ref } from 'vue';
import { propGetThemeVar, useTheme, type ViewStyle } from '../theme/ThemeDefine';
import { configPadding, DynamicColor, DynamicSize, selectStyleType } from '../theme/ThemeTools';
import type { IconProps } from './Icon.vue';
import type { FlexProps } from '../layout/FlexView.vue';
import Text from './Text.vue';
import ActivityIndicator from './ActivityIndicator.vue';
import Icon from './Icon.vue';
import Touchable from '../feedback/Touchable.vue';
import type { ButtonGroupContext } from './ButtonGroup.vue';
import { useChildLinkChild } from '../composeabe/ChildItem';
import type { TextProps } from './Text';

export type ButtonType = 'default'|'primary'|'success'|'warning'|'danger'|'custom'|'text';
export type ButtomSizeType = 'small'|'medium'|'large'|'larger'|'mini';

export interface ButtonProp {
  /**
   * 按钮文字
   */
  text?: string,
  /**
   * 按钮文字的额外属性
   */
  textProps?: TextProps,
  /**
   * 按钮支持 default、primary、success、warning、danger、custom 自定义 六种类型
   * @default 'default'
   */
  type?: ButtonType,
  /**
   * 占满父级主轴
   * @default false
   */
  block?: boolean,
  /**
   * * plain 将按钮设置为朴素按钮，朴素按钮的文字为按钮颜色，背景为白色。
   * * light 将按钮设置为浅色按钮，浅色按钮的文字为按钮颜色，背景为主色调浅色。
   * @default 'default'
   */
  scheme?: 'default'|'plain'|'light',
  /**
   * 通过 loading 属性设置按钮为加载状态，加载状态下默认会隐藏按钮文字，可以通过 loadingText 设置加载状态下的文字。
   * @default false
   */
  loading?: boolean,
  /**
   * 加载状态下的文字。
   * @default false
   */
  loadingText?: string,
  /**
   * 加载状态圆圈颜色
   */
  loadingColor?: string,
  /**
   * 按钮形状 通过 square 设置方形按钮，通过 round 设置圆形按钮。
   * @default 'round'
   */
  shape?: 'square'|'round',
  /**
   * 左侧图标。支持 Icon 组件里的所有图标，也可以传入图标的图片 URL（http/https）。
   */
  icon?: string,
  /**
   * 当使用图标时，左侧图标的附加属性
   */
  iconProps?: IconProps;
  /**
   * 图标与文字之间的间距
   * @default 10
   */
  iconMargin?: number|string;
  /**
   * 右侧图标。支持 Icon 组件里的所有图标，也可以传入图标的图片 URL（http/https）。
   */
  rightIcon?: string,
  /**
   * 当使用图标时，右侧图标的附加属性
   */
  rightIconProps?: IconProps;
  /**
   * 是否可以点击
   * @default true
   */
  touchable?: boolean,
  /**
   * 当按扭为round圆形按扭时的圆角大小。
   * @default 5
   */
  radius?: number|string,
  /**
   * 按钮尺寸. 支持 large、medium、small、mini 四种尺寸。
   * @default 'medium'
   */
  size?: ButtomSizeType,
  /**
   * 通过 color 属性可以自定义按钮的背景颜色，仅在 type 为 `custom` 时有效
   * @default grey
   */
  color?: string;
  /**
   * 按钮文字的颜色。
   */
  textColor?: string;
  /**
   * 按下时按钮文字的颜色。
   */
  pressedTextColor?: string;
  /**
   * 按钮文字的样式。
   */
  textStyle?: object;
  /**
   * 按下时的颜色，仅在 type 为 `custom` 时有效
   * @default PressedColor(primary)
   */
  pressedColor?: string;
  /**
   * 禁用时的颜色，仅在 type 为 `custom` 时有效
   * @default grey
   */
  disabledColor?: string;
  /**
   * 自定义样式
   */
  innerStyle?: object,
  /**
   * 按扭的文字，等同于 text 属性
   */
  children?: string;
  /**
   * 强制控制按钮的边距
   * * 如果是数字，则设置所有方向边距
   * * 两位数组 [vetical,horizontal]
   * * 四位数组 [top,right,down,left]
   */
  padding?: number|number[],
  /**
   * 外层容器参数
   */
  viewProps?: FlexProps,

  formType?: string;
  openType?: string;
  appParameter?: string;
}

defineOptions({
  options: {
    styleIsolation: "shared",
    virtualHost: true,
  }
})

const emit = defineEmits([ 
  'click',
])

const themeContext = useTheme();

const props = withDefaults(defineProps<ButtonProp>(), {
  touchable: true,
  loading: false,
  color: () => propGetThemeVar('ButtonColor', 'primary'),
  pressedColor: () => propGetThemeVar('ButtonPressedColor', 'pressed.primary'),
  disabledColor: () => propGetThemeVar('ButtonDisabledColor', 'grey'),
  type: () => propGetThemeVar('ButtonType', 'default'),
  size: () => propGetThemeVar('ButtonSize', 'medium'),
  block: () => propGetThemeVar('ButtonBlock', false),
  radius: () => propGetThemeVar('ButtonRadius', 16),
  iconMargin: () => propGetThemeVar('ButtonIconMargin', 10),
  shape: () => propGetThemeVar('ButtonShape', "round"),
});

const FonstSizes = computed(() => ({
  mini: themeContext.resolveThemeSize('ButtonMiniFonstSize', 'fontSize.sm'),
  small: themeContext.resolveThemeSize('ButtonSmallFonstSize', 'fontSize.sm'),
  medium: themeContext.resolveThemeSize('ButtonMediumFonstSize', 'fontSize.md'),
  large: themeContext.resolveThemeSize('ButtonLargeFonstSize', 'fontSize.lg'),
  larger: themeContext.resolveThemeSize('ButtonLargerFonstSize', 'fontSize.xl'),
}));
const themeVars = themeContext.getVars({
  ButtonBorderWidth: 1.5,
  ButtonDisableOpacity: 0.5,
});
const themeStyles = themeContext.useThemeStyles({
  plainButtonDefault: {
    borderStyle: 'solid',
    borderWidth: DynamicSize('ButtonBorderWidth', 1.5),
    borderColor: DynamicColor('ButtonPlainDefaultBorderColor', 'border.default'),
    color: DynamicColor('ButtonPlainDefaultColor', 'text.content'),
  },
  plainButtonPrimary: {
    borderStyle: 'solid',
    borderWidth: DynamicSize('ButtonBorderWidth', 1.5),
    borderColor: DynamicColor('ButtonPlainPrimaryBorderColor', 'primary'),
    color: DynamicColor('ButtonPlainPrimaryColor', 'primary'),
  },
  plainButtonSuccess: {
    borderStyle: 'solid',
    borderWidth: DynamicSize('ButtonBorderWidth', 1.5),
    borderColor: DynamicColor('ButtonPlainSuccessBorderColor', 'success'),
    color: DynamicColor('ButtonPlainSuccessColor', 'success'),
  },
  plainButtonWarning: {
    borderStyle: 'solid',
    borderWidth: DynamicSize('ButtonBorderWidth', 1.5),
    borderColor: DynamicColor('ButtonPlainWarningBorderColor', 'warning'),
    color: DynamicColor('ButtonPlainWarningColor', 'warning'),
  },
  plainButtonDanger: {
    borderStyle: 'solid',
    borderWidth: DynamicSize('ButtonBorderWidth', 1.5),
    borderColor: DynamicColor('ButtonPlainDangerBorderColor', 'danger'),
    color: DynamicColor('ButtonPlainDangerColor', 'danger'),
  },
  lightButtonDefault: {
    backgroundColor: DynamicColor('ButtonLightDefaultBackgroundColor', 'background.button'),
    color: DynamicColor('ButtonLightDefaultColor', 'text.content'),
  },
  lightButtonPrimary: {
    backgroundColor: DynamicColor('ButtonLightPrimaryBackgroundColor', 'background.primary'),
    color: DynamicColor('ButtonLightPrimaryColor', 'text.primary'),
  },
  lightButtonSuccess: {
    backgroundColor: DynamicColor('ButtonLightSuccessBackgroundColor', 'background.success'),
    color: DynamicColor('ButtonLightSuccessColor', 'text.success'),
  },
  lightButtonWarning: {
    backgroundColor: DynamicColor('ButtonLightWarningBackgroundColor', 'background.warning'),
    color: DynamicColor('ButtonLightWarningColor', 'text.warning'),
  },
  lightButtonDanger: {
    backgroundColor: DynamicColor('ButtonLightDangerBackgroundColor', 'background.danger'),
    color: DynamicColor('ButtonLightDangerColor', 'text.danger'),
  },
  buttonSizeLarger: {
    paddingVertical: DynamicSize('ButtonPaddingVerticalLarger', 25),
    paddingHorizontal: DynamicSize('ButtonPaddingHorizontalLarger', 30),
  },
  buttonSizeLarge: {
    paddingVertical: DynamicSize('ButtonPaddingVerticalLarge', 20),
    paddingHorizontal: DynamicSize('ButtonPaddingHorizontalLarge', 25),
  },
  buttonSizeMedium: {
    paddingVertical: DynamicSize('ButtonPaddingVerticalMedium', 15),
    paddingHorizontal: DynamicSize('ButtonPaddingHorizontalMedium', 20),
  },
  buttonSizeSmall: {
    paddingVertical: DynamicSize('ButtonPaddingVerticalSmall', 10),
    paddingHorizontal: DynamicSize('ButtonPaddingHorizontalSmall', 15),
  },
  buttonSizeMini: {
    paddingVertical: DynamicSize('ButtonPaddingVerticalMini', 5),
    paddingHorizontal: DynamicSize('ButtonPaddingHorizontalMini', 6),
  },
  buttonDefault: {
    backgroundColor: DynamicColor('ButtonDefaultBackgroundColor', 'button'),
    color: DynamicColor('ButtonDefaultColor', 'black'),
  },
  buttonPrimary: {
    backgroundColor: DynamicColor('ButtonPrimaryBackgroundColor', 'primary'),
    color: DynamicColor('ButtonPrimaryColor', 'white'),
  },
  buttonSuccess: {
    backgroundColor: DynamicColor('ButtonSuccessBackgroundColor', 'success'),
    color: DynamicColor('ButtonSuccessColor', 'white'),
  },
  buttonWarning: {
    backgroundColor: DynamicColor('ButtonWarningBackgroundColor', 'warning'),
    color: DynamicColor('ButtonWarningColor', 'white'),
  },
  buttonDanger: {
    backgroundColor: DynamicColor('ButtonDangerBackgroundColor', 'danger'),
    color: DynamicColor('ButtonDangerColor', 'white'),
  },
});

//按钮样式生成
const currentStyle = computed(() => {
  const colorStyle = selectStyleType<ViewStyle, ButtonType>(props.type, 'default', 
    selectStyleType(props.scheme, 'default', {
      default: {
        default: themeStyles.buttonDefault.value,
        primary: themeStyles.buttonPrimary.value,
        success: themeStyles.buttonSuccess.value,
        warning: themeStyles.buttonWarning.value,
        danger: themeStyles.buttonDanger.value,
        custom: {
          backgroundColor: themeContext.resolveThemeColor(touchable.value ? props.color : props.disabledColor),
          color: themeContext.resolveThemeColor(props.textColor),
        },
        text: {
          color: themeContext.resolveThemeColor(props.textColor),
        },
      },
      plain: {
        default: themeStyles.plainButtonDefault.value,
        primary: themeStyles.plainButtonPrimary.value,
        success: themeStyles.plainButtonSuccess.value,
        warning: themeStyles.plainButtonWarning.value,
        danger: themeStyles.plainButtonDanger.value,
        custom: {
          borderStyle: 'solid',
          borderWidth: themeContext.resolveThemeSize(themeVars.ButtonBorderWidth),
          borderColor: themeContext.resolveThemeColor(props.color),
          color: themeContext.resolveThemeColor(props.color),
        },
        text: {
          color: themeContext.resolveThemeColor(props.color),
        },
      },
      light: {
        default: themeStyles.lightButtonDefault.value,
        primary: themeStyles.lightButtonPrimary.value,
        success: themeStyles.lightButtonSuccess.value,
        warning: themeStyles.lightButtonWarning.value,
        danger: themeStyles.lightButtonDanger.value,
        custom: {
          backgroundColor: themeContext.resolveThemeColor(touchable.value ? props.color : props.disabledColor),
          color: themeContext.resolveThemeColor(props.textColor),
        },
        text: {
          color: themeContext.resolveThemeColor(props.color),
        },
      },
    })
  );

  const speicalStyle : ViewStyle = {
    opacity: touchable.value ? 1 : themeVars.ButtonDisableOpacity,
    borderRadius: props.shape === 'round' ? themeContext.resolveThemeSize(props.radius) : 0,
  };

  if (props.shape === 'round') {
    if (noLeftRadius.value) {
      speicalStyle.borderTopLeftRadius = 0;
      speicalStyle.borderBottomLeftRadius = 0;
    }
    if (noRightRadius.value) {
      speicalStyle.borderTopRightRadius = 0;
      speicalStyle.borderBottomRightRadius = 0;
    }
  }

  //自定义状态下的禁用颜色
  if (props.disabledColor && !touchable.value && props.type === 'custom')
    speicalStyle.backgroundColor = themeContext.resolveThemeColor(props.disabledColor);

  const sizeStyle = selectStyleType<ViewStyle, ButtomSizeType>(props.size, 'medium', {
    large: themeStyles.buttonSizeLarge.value,
    larger: themeStyles.buttonSizeLarger.value,
    medium: themeStyles.buttonSizeMedium.value,
    small: themeStyles.buttonSizeSmall.value,
    mini: themeStyles.buttonSizeMini.value,
  });
  //if (props.shape === 'round')
  //  sizeStyle.paddingHorizontal = `calc(${sizeStyle.paddingHorizontal} + ${themeContext.resolveSize(props.radius / 4)})`;

  //内边距样式的强制设置
  configPadding(speicalStyle, themeContext, props.padding);

  return {
    color: (colorStyle).color,
    style: {
      ...colorStyle,
      ...sizeStyle,
      ...speicalStyle,
    },
  };
});

const state = ref('');

const currentText =  computed(() => (props.loading ? (props.loadingText || props.text) : props.text));
const textColorFinal = computed(() => (
  state.value === 'active' ?
    themeContext.resolveThemeColor(props.pressedTextColor) :
    themeContext.resolveThemeColor(props.textColor)
) || currentStyle.value.color);
const finalPressedColor = computed(() => {
  if (props.type === 'custom')
    return themeContext.resolveThemeColor(props.pressedColor);
  return (themeContext.resolveThemeColor((
    props.scheme === 'plain' 
    || props.scheme === 'light' 
    || props.type === 'text'
  ) ? 
    'pressed.notice' : 
    'pressed.' + props.type))
});

//按钮组的处理

const buttonGroupContext = inject<ButtonGroupContext>('buttonGroupContext', undefined as any);
const { position } = useChildLinkChild(() => buttonGroupContext?.getPosition());

const noRightRadius = computed(() => buttonGroupContext?.mergeRadius.value && position.value !== buttonGroupContext.length.value - 1);
const noLeftRadius = computed(() => buttonGroupContext?.mergeRadius.value && position.value !== 0);

const touchable = computed(() => props.touchable !== false && !buttonGroupContext?.groupDisabled.value);
</script>

<style>
.nana-button {
  width: auto;
  user-select: none;
  cursor: pointer;
  appearance: none;
}
.nana-button-inner {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  background-color: transparent;
  border: none;
  outline: none;
  line-height: auto;
  padding: 0;
  margin: 0;
  min-height: 0;
}
.nana-button-inner::after {
  display: none;
}
.nana-button-auto {
  flex-shrink: 0;
  flex-grow: 0;
  flex-basis: auto;
}
.nana-button-block {
  align-self: stretch;
  max-width: 100%;
}
</style>

