import { formatTime } from "../../../utils/common.js";

const isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0;

export class ProgressComponent {
  constructor(player) {
    this.player = player;
    this.container = null;
    this.isDragging = false;
    this.isTouchDragging = false;
    this.tooltipTimeout = null;

    this.init();
  }

  init() {
    this.createElements();
    this.setupEventListeners();
    this.bindPlayerEvents();
  }

  createElements() {
    // Custom progress bar container
    this.container = document.createElement("div");
    this.container.className = "pp-progress-container";

    this.container.innerHTML = `
      <div class="pp-progress-loaded"></div>
      <div class="pp-progress-played"></div>
      <div class="pp-progress-handle"></div>
      <div class="pp-progress-tooltip">00:00</div>
    `;

    // Get elements
    this.loadedBar = this.container.querySelector(".pp-progress-loaded");
    this.playedBar = this.container.querySelector(".pp-progress-played");
    this.handle = this.container.querySelector(".pp-progress-handle");
    this.progressTooltip = this.container.querySelector(".pp-progress-tooltip");
  }

  updateProgress() {
    const currentTime = this.player.getPosition() || 0;
    const duration = this.player.getDuration() || 0;
    const buffered = this.player.getBufferInfo()?.bufferEnd() || 0;

    if (duration > 0) {
      const playedPercent = (currentTime / duration) * 100;
      this.playedBar.style.width = `${playedPercent}%`;
      this.handle.style.left = `${playedPercent}%`;

      // Update loaded progress if buffered data is available
      if (buffered > 0) {
        const loadedPercent = (buffered / duration) * 100;
        this.loadedBar.style.width = `${loadedPercent}%`;
      }
    }
  }

  seekToPosition(e) {
    const rect = this.container.getBoundingClientRect();
    const clientX =
      e.clientX || (e.touches && e.touches[0] ? e.touches[0].clientX : 0);
    const percent = Math.max(
      0,
      Math.min(1, (clientX - rect.left) / rect.width)
    );
    const duration = this.player.getDuration();
    const seekTime = percent * duration;

    if (duration && !isNaN(duration)) {
      this.player.seek(seekTime);
    }
  }

  updateTooltipPosition(e) {
    const rect = this.container.getBoundingClientRect();
    const clientX =
      e.clientX || (e.touches && e.touches[0] ? e.touches[0].clientX : 0);
    const percent = Math.max(
      0,
      Math.min(1, (clientX - rect.left) / rect.width)
    );
    const duration = this.player.getDuration();

    if (duration && !isNaN(duration)) {
      const seekTime = percent * duration;
      this.progressTooltip.textContent = formatTime(seekTime);

      // Position tooltip at mouse/touch position
      const leftPercent = percent * 100;
      this.progressTooltip.style.left =
        leftPercent < 1
          ? "3px"
          : leftPercent > 99
          ? "calc(100% - 3px)"
          : `${leftPercent}%`;
    }
  }

  showTooltip(e) {
    clearTimeout(this.tooltipTimeout);
    this.progressTooltip.style.opacity = "1";
    this.progressTooltip.style.visibility = "visible";
    this.updateTooltipPosition(e);
  }

  hideTooltip(delay = 0) {
    clearTimeout(this.tooltipTimeout);
    this.tooltipTimeout = setTimeout(() => {
      this.progressTooltip.style.opacity = "0";
      this.progressTooltip.style.visibility = "hidden";
    }, delay);
  }

  handleDrag(e) {
    if (this.isDragging || this.isTouchDragging) {
      this.seekToPosition(e);
    }
    this.updateTooltipPosition(e);
  }

  setupEventListeners() {
    if (!isTouchDevice) {
      // Mouse events
      this.container.addEventListener("click", (e) => this.seekToPosition(e));

      this.container.addEventListener("mousedown", (e) => {
        this.isDragging = true;
        this.seekToPosition(e);
      });

      document.addEventListener("mousemove", (e) => this.handleDrag(e));
      document.addEventListener("mouseup", () => {
        this.isDragging = false;
        if (!this.container.matches(":hover")) {
          this.hideTooltip();
        }
      });

      // Show tooltip on hover with position tracking
      this.container.addEventListener("mouseenter", (e) => {
        this.showTooltip(e);
      });

      this.container.addEventListener("mouseleave", () => {
        if (!this.isDragging) {
          this.hideTooltip();
        }
      });
    } else {
      // Touch events for mobile
      this.container.addEventListener("touchstart", (e) => {
        e.preventDefault();
        this.isTouchDragging = true;
        this.showTooltip(e);
        this.seekToPosition(e);
      });

      this.container.addEventListener("touchmove", (e) => {
        e.preventDefault();
        if (this.isTouchDragging) {
          this.handleDrag(e);
        }
      });

      this.container.addEventListener("touchend", (e) => {
        e.preventDefault();
        this.isTouchDragging = false;
        // Hide tooltip after a delay on touch end
        this.hideTooltip(1000);
      });

      // Handle touch cancel
      this.container.addEventListener("touchcancel", (e) => {
        e.preventDefault();
        this.isTouchDragging = false;
        this.hideTooltip();
      });
    }
  }

  bindPlayerEvents() {
    this.player.on("timeupdate", this.updateProgress.bind(this));
    this.player.on("progress", this.updateProgress.bind(this));
    this.player.on("loadedmetadata", this.updateProgress.bind(this));
    this.player.on("durationchange", this.updateProgress.bind(this));
  }

  cleanup() {
    // Clear tooltip timeout
    if (this.tooltipTimeout) {
      clearTimeout(this.tooltipTimeout);
      this.tooltipTimeout = null;
    }

    // TODO: Add cleanup for event listeners
  }
}
