<template>
  <view
    :style="{
      ...themeStyles.bar.value,
      ...innerStyle,
    }"
  >
    <view
      :id="id"
      :style="{
        ...themeStyles.barInner.value,
        ...innerBarStyle,
      }"
      @mousedown="handleTouchStart"
      @touchstart="handleTouchStart"
      @touchmove="handleTouchMove"
      @mousemove="handleTouchMove"
      @touchend="handleTouchEnd"
      @mouseup="handleTouchEnd"
      @touchcancel="handleTouchEnd"
    > 
      <view 
        v-for="(value, i) in data"
        :key="i"
        :style="{
          ...themeStyles.barItem.value,
          ...(activeIndex === i ? themeStyles.barItemActive.value : {}),
          ...props.itemStyle,
          ...(activeIndex === i ? props.activeItemStyle : {}),
          ...sizeStyle,
        }"
      >
        <text :style="{
          ...themeStyles.barItemText.value,
          ...(activeIndex === i ? themeStyles.barItemTextActive.value : {}),
          ...props.itemTextStyle,
          ...(activeIndex === i ? props.activeItemTextStyle : {}),
        }">
          {{ value }}
        </text>
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">
import { computed, getCurrentInstance } from 'vue';
import { useTheme, type TextStyle, type ViewStyle } from '../theme/ThemeDefine';
import { DynamicColor, DynamicSize, DynamicVar } from '../theme/ThemeTools';
import { MathUtis, RandomUtils } from '@imengyu/imengyu-utils';

const themeContext = useTheme();

export interface IndexBarProps {
  /**
   * 数据
   */
  data: string[],
  /**
   * 每个条目的大小（像素）
   * @default 20
   */
  itemSize?: number,
  /**
   * 每个条目的间距（像素）
   * @default 5
   */
  itemSpace?: number,
  innerStyle?: ViewStyle,
  innerBarStyle?: ViewStyle,
  /**
   * 每个条目的样式
   */
  itemStyle?: ViewStyle,
  /**
   * 条目激活时的样式
   */
  activeItemStyle?: ViewStyle,
  /**
   * 条目文字样式
   */
  itemTextStyle?: TextStyle,
  /**
   * 条目激活时的文字样式
   */
  activeItemTextStyle?: TextStyle,
  /**
   * 激活的索引
   */
  activeIndex?: number,
}

const emit = defineEmits([ 'update:activeIndex', 'drag' ]);
const props = withDefaults(defineProps<IndexBarProps>(), {
  activeIndex: -1,
  itemSize: 20,
  itemSpace: 5,
  data: () => [],
});

const id = 'IndexBarDarg' + RandomUtils.genNonDuplicateIDHEX(12);
const sizeStyle = computed(() => ({
  width: `${props.itemSize}px`,
  height: `${props.itemSize}px`,
  marginTop: `${props.itemSpace}px`,
}));
const themeStyles = themeContext.useThemeStyles({
  bar: {
    position: 'absolute',
    left: DynamicSize('IndexBarLeft', undefined),
    right: DynamicSize('IndexBarRight', 0),
    top: DynamicSize('IndexBarTop', 0),
    bottom: DynamicSize('IndexBarBottom', 0),
    zIndex: DynamicVar('IndexBarZIndex', 10),
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    pointerEvents: 'none',
  },
  barInner: {
    position: 'relative',
    paddingRight: DynamicSize('IndexBarPaddingRight', 20),
    paddingLeft: DynamicSize('IndexBarPaddingLeft', 0),
    paddingTop: DynamicSize('IndexBarPaddingTop', 0),
    paddingBottom: DynamicSize('IndexBarPaddingBottom', 0),
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    pointerEvents: 'auto',
  },
  barItem: {
    display: 'flex',
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: DynamicColor('IndexBarItemBackgroundColor', 'transparent'),
    borderRadius: DynamicSize('IndexBarItemBorderRadius', 20),
  },
  barItemActive: {
    backgroundColor: DynamicColor('IndexBarItemActiveBackgroundColor', 'primary'),
    borderRadius: DynamicSize('IndexBarItemBorderRadius', 20),
  },
  barItemTextActive: {
    color: DynamicColor('IndexBarItemActiveTextColor', 'white'),
  },
  barItemText: {
    color: DynamicColor('IndexBarItemTextColor', 'text.content'),
    fontSize: DynamicSize('IndexBarItemTextFontSize', 24),
  },
  indicator: {
    position: 'absolute',
    width: DynamicSize('IndexBarIndicatorWidth', 100),
    height: DynamicSize('IndexBarIndicatorHeight', 100),
    backgroundColor: DynamicColor('IndexBarIndicatorBackgroundColor', 'mask.default'),
    borderRadius: DynamicSize('IndexBarIndicatorBorderRadius', 100),
    overflow: 'hidden',
    top: DynamicSize('IndexBarIndicatorTop', '35%'),
    left: DynamicSize('IndexBarIndicatorLeft', '50%'),
    marginLeft: DynamicSize('IndexBarIndicatorMarginLeft', -50),
    zIndex: DynamicVar('IndexBarIndicatorZIndex', 20),
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
  },
  indicatorText: {
    color: DynamicVar('IndexBarIndicatorTextColor', 'white'),
    fontSize: DynamicVar('IndexBarIndicatorTextFontSize', 50),
    fontWeight: DynamicVar('IndexBarIndicatorTextFontWeight', 'bold'),
  },

});

let dragging = false;
let absTop = 0;
const instance = getCurrentInstance();

function handleDrag(e: number) {
  const y = MathUtis.limitNumber(e - absTop, 1, (props.itemSize + props.itemSpace) * props.data.length);
  const v = Math.ceil((y) / (props.itemSize + props.itemSpace) - 1);
  if (v !== props.activeIndex) {
    emit('update:activeIndex', v);
    emit('drag', v);
  }
}
function handleTouchStart(e: any) {
  dragging = true;
  e.preventDefault();
  e.stopPropagation();
  const query = uni.createSelectorQuery();
  query
    .in(instance)
    .select('#' + id)
    .boundingClientRect((res) => {
      if (res)
        absTop = (res as any).top;
      handleDrag(e.touches[0]?.clientY);
    }).exec();
}
function handleTouchMove(e: any) {
  if (!dragging) 
    return;
  e.stopPropagation();
  e.preventDefault();
  handleDrag(e.touches[0].clientY);
}
function handleTouchEnd(e: any) {
  if (!dragging) 
    return;

  e.stopPropagation();
  e.preventDefault();
  dragging = false;
}
</script>