import streamDeck, { SingletonAction } from "@elgato/streamdeck";
import { wsManager } from "../websocket-manager.js";
import { generateRecordButton } from "../image-generator.js";

/**
 * Record Action (toggle)
 *
 * Toggles recording on/off with confirmation in both directions:
 *
 * Not recording:
 * - First press: button shows CONFIRM (2s timeout)
 * - Second press: starts recording, button becomes STOP
 * - Timeout: returns to REC
 *
 * Recording:
 * - First press: button shows CONFIRM (2s timeout)
 * - Second press: stops recording, button becomes REC
 * - Timeout: returns to STOP
 */
export class RecordAction extends SingletonAction {
  manifestId = "com.djliveplaylist.record";

  // Store action references for updating button images
  actions = new Map();

  // Track recording state
  isRecording = false;

  constructor() {
    super();

    // Update buttons when connection state changes
    wsManager.on("connected", () => this.updateAllButtons());
    wsManager.on("disconnected", () => {
      this.isRecording = false;
      this.cancelAllConfirmations();
      this.updateAllButtons();
    });

    // Listen for recording status updates from the app
    wsManager.on("RECORDING_STATUS", (payload) => {
      this.isRecording = payload.is_recording;
      this.cancelAllConfirmations();
      this.updateAllButtons();
    });
  }

  onWillAppear(ev) {
    const actionId = ev.action.id;
    this.actions.set(actionId, {
      action: ev.action,
      confirmTimeout: null,
      isConfirming: false,
    });
    this.updateButton(actionId);
  }

  onWillDisappear(ev) {
    const actionId = ev.action.id;
    const entry = this.actions.get(actionId);
    if (entry?.confirmTimeout) {
      clearTimeout(entry.confirmTimeout);
    }
    this.actions.delete(actionId);
  }

  async onKeyDown(ev) {
    if (!wsManager.isConnected) {
      streamDeck.logger.warn("Cannot toggle recording: not connected to DLP");
      return;
    }

    const actionId = ev.action.id;
    const entry = this.actions.get(actionId);
    if (!entry) return;

    if (entry.isConfirming) {
      // Second press — confirm the action
      clearTimeout(entry.confirmTimeout);
      entry.confirmTimeout = null;
      entry.isConfirming = false;

      if (this.isRecording) {
        wsManager.send("STOP_RECORDING", {});
        streamDeck.logger.info("Stop recording confirmed");
      } else {
        wsManager.send("START_RECORDING", {});
        streamDeck.logger.info("Start recording confirmed");
      }
    } else {
      // First press — enter confirmation state
      entry.isConfirming = true;
      this.updateButton(actionId);

      // Auto-cancel after 2 seconds
      entry.confirmTimeout = setTimeout(() => {
        entry.isConfirming = false;
        entry.confirmTimeout = null;
        this.updateButton(actionId);
        streamDeck.logger.info("Recording confirmation timed out");
      }, 2000);
    }
  }

  cancelAllConfirmations() {
    for (const [actionId, entry] of this.actions.entries()) {
      if (entry.confirmTimeout) {
        clearTimeout(entry.confirmTimeout);
        entry.confirmTimeout = null;
      }
      entry.isConfirming = false;
    }
  }

  async updateButton(actionId) {
    const entry = this.actions.get(actionId);
    if (!entry) return;

    let state = "idle";
    if (this.isRecording) {
      state = entry.isConfirming ? "confirm-stop" : "recording";
    } else {
      state = entry.isConfirming ? "confirm" : "idle";
    }

    const image = generateRecordButton({
      isConnected: wsManager.isConnected,
      state,
    });
    entry.action.setImage(image);
  }

  updateAllButtons() {
    for (const actionId of this.actions.keys()) {
      this.updateButton(actionId);
    }
  }
}
