import { Task } from "@lit/task";
import { LitElement, css, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import { createRef, ref } from "lit/directives/ref.js";
import { EF_INTERACTIVE } from "../EF_INTERACTIVE.js";
import { EFSourceMixin } from "./EFSourceMixin.js";
import { EFTemporal } from "./EFTemporal.js";
import { FetchMixin } from "./FetchMixin.js";

@customElement("ef-image")
export class EFImage extends EFTemporal(
  EFSourceMixin(FetchMixin(LitElement), {
    assetType: "image_files",
  }),
) {
  static styles = [
    css`
      :host {
        display: block;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      canvas, img {
        all: inherit;
      }
    `,
  ];

  imageRef = createRef<HTMLImageElement>();
  canvasRef = createRef<HTMLCanvasElement>();

  #assetId: string | null = null;
  @property({ type: String, attribute: "asset-id", reflect: true })
  set assetId(value: string | null) {
    this.#assetId = value;
  }

  get assetId() {
    return this.#assetId ?? this.getAttribute("asset-id");
  }

  render() {
    const assetPath = this.assetPath();
    const isDirectUrl = this.isDirectUrl(assetPath);
    return isDirectUrl
      ? html`<img ${ref(this.imageRef)} src=${assetPath} />`
      : html`<canvas ${ref(this.canvasRef)}></canvas>`;
  }

  private isDirectUrl(src: string): boolean {
    return src.startsWith("http://") || src.startsWith("https://");
  }

  assetPath() {
    if (this.assetId) {
      return `${this.apiHost}/api/v1/image_files/${this.assetId}`;
    }
    if (this.isDirectUrl(this.src)) {
      return this.src;
    }
    return `/@ef-image/${this.src}`;
  }

  get hasOwnDuration() {
    return this.hasExplicitDuration;
  }

  fetchImage = new Task(this, {
    autoRun: EF_INTERACTIVE,
    args: () => [this.assetPath(), this.fetch] as const,
    task: async ([assetPath, fetch], { signal }) => {
      // For direct URLs, skip task - src is set directly in render
      if (this.isDirectUrl(assetPath)) {
        return;
      }

      // For asset-id and local files, use canvas as before
      const response = await fetch(assetPath, { signal });
      const image = new Image();
      image.src = URL.createObjectURL(await response.blob());

      await new Promise((resolve, reject) => {
        image.onload = resolve;
        image.onerror = reject;
      });

      if (!this.canvasRef.value) throw new Error("Canvas not ready");
      const ctx = this.canvasRef.value.getContext("2d");
      if (!ctx) throw new Error("Canvas 2d context not ready");
      this.canvasRef.value.width = image.width;
      this.canvasRef.value.height = image.height;
      ctx.drawImage(image, 0, 0);
    },
  });

  frameTask = new Task(this, {
    autoRun: EF_INTERACTIVE,
    args: () => [this.fetchImage.status] as const,
    task: async () => {
      await this.fetchImage.taskComplete;
    },
  });
}

declare global {
  interface HTMLElementTagNameMap {
    "ef-image": EFImage;
  }
}
