import { DOCUMENT } from '@angular/common';
import { Injectable, inject } from '@angular/core';
import { environment } from '../../../../../environments/environment';

export interface ExperimentalVlcPlayerOptions {
  container: HTMLElement;
  sourceUrl: string;
  filename: string;
  mime: string;
}

export interface ExperimentalVlcPlayerHandle {
  destroy?: () => void;
}

export interface ExperimentalVlcRuntime {
  createPlayer: (options: ExperimentalVlcPlayerOptions) => ExperimentalVlcPlayerHandle | Promise<ExperimentalVlcPlayerHandle>;
  isPlaceholder?: boolean;
}

declare global {
  interface Window {
    MetoYouVlcJs?: ExperimentalVlcRuntime;
  }
}

const VLC_RUNTIME_SCRIPT_URL = environment.experimentalMedia.vlcRuntimeScriptUrl;

@Injectable({ providedIn: 'root' })
export class ExperimentalVlcRuntimeService {
  private readonly document = inject(DOCUMENT);
  private runtimeLoadPromise: Promise<ExperimentalVlcRuntime> | null = null;

  async createPlayer(options: ExperimentalVlcPlayerOptions): Promise<ExperimentalVlcPlayerHandle> {
    const runtime = await this.loadRuntime();

    if (runtime.isPlaceholder) {
      throw new Error('No VLC.js runtime is bundled. Use Open in Electron, or replace /vlcjs/metoyou-vlc-player.js with a real runtime adapter.');
    }

    return runtime.createPlayer(options);
  }

  async hasBundledRuntime(): Promise<boolean> {
    try {
      const runtime = await this.loadRuntime();

      return !!runtime.createPlayer && !runtime.isPlaceholder;
    } catch {
      return false;
    }
  }

  private loadRuntime(): Promise<ExperimentalVlcRuntime> {
    if (this.document.defaultView?.MetoYouVlcJs?.createPlayer) {
      return Promise.resolve(this.document.defaultView.MetoYouVlcJs);
    }

    this.runtimeLoadPromise ??= new Promise<ExperimentalVlcRuntime>((resolve, reject) => {
      const script = this.document.createElement('script');

      script.src = VLC_RUNTIME_SCRIPT_URL;
      script.async = true;

      script.onload = () => {
        const runtime = this.document.defaultView?.MetoYouVlcJs;

        if (!runtime?.createPlayer) {
          reject(new Error('The experimental VLC.js runtime did not register a MetoYouVlcJs.createPlayer adapter.'));
          return;
        }

        resolve(runtime);
      };

      script.onerror = () => reject(new Error(`The experimental VLC.js runtime was not found at ${VLC_RUNTIME_SCRIPT_URL}.`));

      this.document.head.appendChild(script);
    });

    return this.runtimeLoadPromise;
  }
}
