// gesture_handler.ts
import { HandGesture, HandInfo } from "@/hand_landmark/detector";
import use_app_store from "@/store/app";

// WebSocket数据类型定义
enum WsDataType {
  // 系统消息类型
  INFO = "info",
  SUCCESS = "success",
  WARNING = "warning",
  ERROR = "error",

  // 鼠标操作类型
  MOUSE_MOVE = "mouse_move",
  MOUSE_CLICK = "mouse_click",

  // 键盘操作类型
  SEND_KEYS = "send_keys",

}

interface WsData {
  type: WsDataType;
  msg?: string;
  duration?: number;
  title?: string;
  data?: {
    x?: number;
    y?: number;
    key_str?: string;
  };
}
/**
 * 动作触发器类 - 负责发送操作命令到系统
 * 主要职责：
 * 1. 维护WebSocket连接
 * 2. 提供各种操作方法（移动鼠标、点击等）
 * 3. 发送通知
 */
export class TriggerAction {
  private ws: WebSocket | null = null;

  constructor() {
    this.connectWebSocket();
  }

  private connectWebSocket() {
    try {
      this.ws = new WebSocket("ws://127.0.0.1:62334/ws_wavecontrol");
      this.ws.onmessage = (event: MessageEvent) => {
        const response: WsData = JSON.parse(event.data);
        const app_store = use_app_store();
        app_store.sub_window_info(response.msg || "");
      };
      this.ws.onopen = () => {
        console.log("ws_wavecontrol connected");
      };
      this.ws.onclose = () => {
        console.log("ws_wavecontrol closed, retrying...");
        this.ws = null;
        setTimeout(() => this.connectWebSocket(), 3000);
      };
      this.ws.onerror = (error) => {
        console.error("ws_wavecontrol error:", error);
        this.ws?.close();
      };
    } catch (error) {
      console.error("Failed to create WebSocket instance:", error);
      this.ws = null;
      setTimeout(() => this.connectWebSocket(), 1000);
    }
  }

  private send(data: { type: WsDataType } & Partial<Omit<WsData, "type">>) {
    const message: WsData = {
      type: data.type,
      msg: data.msg || "",
      title: data.title || "wavecontrol",
      duration: data.duration || 1,
      data: data.data || {},
    };
    console.log("👉 正在发送指令给后端：", message);
    this.ws?.send(JSON.stringify(message));
  }

  moveMouse(x: number, y: number) {
    this.send({
      type: WsDataType.MOUSE_MOVE,
      data: { x, y },
    });
  }

  clickMouse() {
    this.send({
      type: WsDataType.MOUSE_CLICK,
    });
  }
}

// 手势处理
export class GestureHandler {
  private triggerAction: TriggerAction;
  private previousGesture: HandGesture | null = null; // 上一个识别到的手势
  private previousGestureCount: number = 0;            // 连续识别到相同手势的次数
  private minGestureCount: number = 5;                 // 最小连续识别次数，达到后才触发操作

  // 屏幕参数，用于将摄像头图像坐标映射到实际屏幕坐标
  private screen_width: number = window.screen.width;
  private screen_height: number = window.screen.height;

  private smoothening = 7; // 平滑系数，用于减少抖动
  private prev_loc_x: number = 0; // 上一帧鼠标X坐标
  private prev_loc_y: number = 0; // 上一帧鼠标Y坐标

  private lastClickTime: number = 0; // 上次点击时间戳（用于点击节流）
  private readonly CLICK_INTERVAL = 500; // 点击最小间隔（ms）

  private app_store: any; // 存储应用状态，比如视频宽高、边界设置等

  constructor() {
    this.triggerAction = new TriggerAction(); // 初始化动作触发器，用于发指令到后端
    this.app_store = use_app_store();         // 获取状态管理对象
  }


  /**
   * 食指竖起 → 鼠标移动
   */
  private handleIndexFingerUp(hand: HandInfo) {
    const indexTip = this.getFingerTip(hand, 1); // 获取食指尖坐标
    if (!indexTip) return;

    try {
      // 将 landmark 坐标转为视频画面坐标（x 轴方向翻转）
      const video_x =
        this.app_store.VIDEO_WIDTH - indexTip.x * this.app_store.VIDEO_WIDTH;
      const video_y = indexTip.y * this.app_store.VIDEO_HEIGHT;

      /**
       * 将值从一个范围映射到另一个范围，用于坐标映射
       */
      function mapRange(
        value: number,
        fromMin: number,
        fromMax: number,
        toMin: number,
        toMax: number
      ): number {
        return (
          ((value - fromMin) * (toMax - toMin)) / (fromMax - fromMin) + toMin
        );
      }

      // 将视频坐标映射为屏幕坐标
      let screenX = mapRange(
        video_x,
        this.app_store.config.boundary_left,
        this.app_store.config.boundary_left + this.app_store.config.boundary_width,
        0,
        this.screen_width
      );

      let screenY = mapRange(
        video_y,
        this.app_store.config.boundary_top,
        this.app_store.config.boundary_top + this.app_store.config.boundary_height,
        0,
        this.screen_height
      );

      // 加入平滑处理，缓解抖动
      screenX = this.prev_loc_x + (screenX - this.prev_loc_x) / this.smoothening;
      screenY = this.prev_loc_y + (screenY - this.prev_loc_y) / this.smoothening;

      // 更新上一帧坐标
      this.prev_loc_x = screenX;
      this.prev_loc_y = screenY;

      // 更新状态，触发鼠标移动指令
      this.app_store.sub_windows.x = screenX + 10;
      this.app_store.sub_windows.y = screenY;
      this.triggerAction.moveMouse(screenX, screenY);
    } catch (error) {
      console.error("处理鼠标移动失败:", error);
    }
  }
  /**
   * 食指 + 大拇指上举 → 鼠标左键点击
   */
  private handleMouseClick() {
    const now = Date.now();
    if (now - this.lastClickTime < this.CLICK_INTERVAL) {
      return; // 距离上次点击时间太短，忽略（节流）
    }
    this.lastClickTime = now;

    // 发送鼠标点击指令
    this.triggerAction.clickMouse();
  }

  /**
   * 处理识别到的手势 → 执行相应动作
   */
  handleGesture(gesture: HandGesture, hand: HandInfo) {
    // 判断手势是否重复，连续计数
    if (gesture === this.previousGesture) {
      this.previousGestureCount++;
    } else {
      this.previousGesture = gesture;
      this.previousGestureCount = 1;
    }

    // 鼠标移动（不需要连续确认）
    if (gesture === HandGesture.ONLY_INDEX_UP) {
      this.handleIndexFingerUp(hand);
      return;
    }

    // 连续识别足够多次 → 触发操作
    if (this.previousGestureCount >= this.minGestureCount) {
      switch (gesture) {
        case HandGesture.INDEX_AND_THUMB_UP: // 自定义为点击手势
          this.handleMouseClick();
          break;

        
      }
    }
  }
  /**
   * 获取指定手指的指尖 landmark
   * fingerIndex: 0=拇指, 1=食指, 2=中指, ...
   */
  private getFingerTip(hand: HandInfo, fingerIndex: number) {
    if (!hand) return null;

    const tipIndices = [4, 8, 12, 16, 20]; // 手指指尖 landmark 的索引
    return hand.landmarks[tipIndices[fingerIndex]];
  }

}

