<template>
  <view 
    :id="id"
    class="nana-swiperow"
    @touchstart="handleTouchStart"
    @touchmove="handleTouchMove"
    @touchend="handleTouchEnd"
    @mousedown="handleTouchStart"
    @mousemove="handleTouchMove"
    @mouseup="handleTouchEnd"
  >
    <view 
      class="inner"
      :style="{
        transition: currentAnim ? 'transform 0.2s ease' : undefined,
        transform: `translateX(${currentOffset}px)`,
      }"
    >
      <view 
        :style="{
          width: leftWidth ? `${leftWidth}px` : 'auto',
          marginLeft: `-${leftWidth}px`,
        }"
        class="left"
        id="left"
      >
        <slot name="left">
          <Button 
            v-for="action in leftActions" 
            :key="action.text" shape="square" 
            :type="action.type" 
            :text="action.text" 
            @click="action.onClick" 
          />
        </slot>
      </view>
      <slot />
      <view 
        id="right"
        :style="{
          width: rightWidth ? `${rightWidth}px` : 'auto',
          marginRight: `-${rightWidth}px`,
        }"
        class="right"
      >
        <slot name="right">
          <Button 
            v-for="action in rightActions" 
            :key="action.text" shape="square" 
            :type="action.type" 
            :text="action.text" 
            @click="action.onClick" 
          />
        </slot>
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">

import { computed, getCurrentInstance, nextTick, onMounted, onUpdated, ref } from 'vue';
import { useTheme } from '../theme/ThemeDefine';
import { RandomUtils } from '@imengyu/imengyu-utils';
import Button, { type ButtonType } from '../basic/Button.vue';

const themeContext = useTheme();

export interface SwipeRowAction {
  /**
   * 操作按钮的文本
   */
  text: string,
  /**
   * 操作按钮的类型
   */
  type: ButtonType,
  /**
   * 操作按钮的点击事件
   */
  onClick?: (e: any) => void,
}

export interface SwipeRowProps {
  /**
   * 手动设置左侧宽度，单位为px
   */
  leftWidth?: number|undefined,
  /**
   * 左侧操作按钮
   */
  leftActions?: SwipeRowAction[],
  /**
   * 手动设置右侧宽度，单位为px
   */
  rightWidth?: number|undefined,
  /**
   * 右侧操作按钮
   */
  rightActions?: SwipeRowAction[],
  /**
   * 是否禁用
   */
  disabled?: boolean,
  /**
   * 是否点击后自动关闭
   * @default true
   */
  autoClose?: boolean,
}

const emit = defineEmits([ 'click' ]);
const props = withDefaults(defineProps<SwipeRowProps>(), {
  rightWidth: 0,
  leftWidth: 0,
  autoClose: true
});

const themeStyles = themeContext.useThemeStyles({
});

const instance = getCurrentInstance();
const measuredLeftWidth = ref(0);
const measuredRightWidth = ref(0);

function measureWidth() {
  function measuredEle(id: string) {
    uni.createSelectorQuery()
      .in(instance)
      .select(`#${id}`)
      .boundingClientRect()
      .exec((res) => {
        if (res[0]) {
          if (id === 'left')
            measuredLeftWidth.value = res[0].width;
          else if (id === 'right')
            measuredRightWidth.value = res[0].width;
        }
      });
  }
  nextTick(() => {
    measuredEle('left');
    measuredEle('right');
  });
}

const currentAnim = ref(false);
const currentOffset = ref(0);

const id = RandomUtils.genNonDuplicateID(12);
let startX = 0;
let pressed = false;
let startOffset = 0;
let lastMovedSize = 0;

const leftWidth = computed(() => props.leftWidth && props.leftWidth > 0 ? props.leftWidth : measuredLeftWidth.value);
const rightWidth = computed(() => props.rightWidth && props.rightWidth > 0 ? props.rightWidth : measuredRightWidth.value);

function handleDrag(x: number) {
  const movedSize = x - startX;
  lastMovedSize = movedSize;
  if (movedSize > 0) {
    currentOffset.value = Math.min(startOffset + movedSize, leftWidth.value);
  } else {
    currentOffset.value = Math.max(startOffset + movedSize, -rightWidth.value);
  }
}

function handleTouchStart(e: any) {
  if (props.disabled)
    return;
  pressed = true;
  e.stopPropagation();
  currentAnim.value = false;
  startOffset = currentOffset.value ;
  startX = e.touches[0]?.clientX;
  lastMovedSize = 0;
}
function handleTouchMove(e: any) {
  if (props.disabled || !pressed)
    return;
  e.stopPropagation();
  handleDrag(e.touches[0]?.clientX);
}
function handleTouchEnd(e: any) {
  pressed = false;
  if (props.disabled)
    return;
  currentAnim.value = true;
  nextTick(() => {
    if (Math.abs(lastMovedSize) > 10) {
      if (currentOffset.value > leftWidth.value / 2)
        currentOffset.value = leftWidth.value;
      else if (currentOffset.value < -rightWidth.value / 2)
        currentOffset.value = -rightWidth.value;
      else 
        currentOffset.value = 0;
    } else if (props.autoClose)
      currentOffset.value = 0;
  });
}

onMounted(() => {
  measureWidth();
});
onUpdated(() => {
  measureWidth();
});
</script>

<style lang="scss">
.nana-swiperow {
  position: relative;
  overflow: visible;

  .left {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    display: flex;
    flex-direction: row;
  }
  .right {
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    display: flex;
    flex-direction: row;
  }
}
</style>