import { CommonModule, NgOptimizedImage } from '@angular/common';
import {
  Component,
  ElementRef,
  HostListener,
  computed,
  effect,
  inject,
  signal,
  viewChildren
} from '@angular/core';
import {
  ScreenShareSourceKind,
  ScreenShareSourceOption,
  ScreenShareSourcePickerService
} from '../../../domains/screen-share';
import { ThemeNodeDirective } from '../../../domains/theme';

@Component({
  selector: 'app-screen-share-source-picker',
  standalone: true,
  imports: [
    CommonModule,
    NgOptimizedImage,
    ThemeNodeDirective
  ],
  templateUrl: './screen-share-source-picker.component.html',
  styleUrl: './screen-share-source-picker.component.scss',
  host: {
    style: 'display: contents;'
  }
})
export class ScreenShareSourcePickerComponent {
  readonly picker = inject(ScreenShareSourcePickerService);
  readonly request = this.picker.request;
  readonly sources = computed(() => this.request()?.sources ?? []);
  readonly screenSources = computed(() => this.sources().filter((source) => source.kind === 'screen'));
  readonly windowSources = computed(() => this.sources().filter((source) => source.kind === 'window'));
  readonly filteredSources = computed(() => {
    return this.activeTab() === 'screen' ? this.screenSources() : this.windowSources();
  });
  readonly hasOpenRequest = computed(() => !!this.request());
  readonly activeTab = signal<ScreenShareSourceKind>('screen');
  readonly includeSystemAudio = signal(false);
  readonly selectedSourceId = signal<string | null>(null);

  private readonly sourceButtons = viewChildren<ElementRef<HTMLButtonElement>>('sourceButton');

  constructor() {
    effect(() => {
      const request = this.request();
      const defaultTab: ScreenShareSourceKind = request?.sources.some((source) => source.kind === 'screen') ? 'screen' : 'window';

      this.activeTab.set(defaultTab);
      this.includeSystemAudio.set(request?.includeSystemAudio ?? false);
    });

    effect(() => {
      const sources = this.filteredSources();
      const selectedSourceId = this.selectedSourceId();

      if (!sources.some((source) => source.id === selectedSourceId)) {
        this.selectedSourceId.set(sources[0]?.id ?? null);
      }

      if (sources.length === 0) {
        return;
      }

      window.requestAnimationFrame(() => {
        const activeSourceId = this.selectedSourceId();
        const targetButton =
          this.sourceButtons().find((button) => button.nativeElement.dataset['sourceId'] === activeSourceId) ?? this.sourceButtons()[0];

        targetButton?.nativeElement.focus();
      });
    });
  }

  @HostListener('document:keydown.escape')
  onEscape(): void {
    if (this.hasOpenRequest()) {
      this.cancel();
    }
  }

  trackSource(_index: number, source: ScreenShareSourceOption): string {
    return source.id;
  }

  setActiveTab(tab: ScreenShareSourceKind): void {
    if (!this.getTabSources(tab).length) {
      return;
    }

    this.activeTab.set(tab);
  }

  getTabCount(tab: ScreenShareSourceKind): number {
    return this.getTabSources(tab).length;
  }

  selectSource(sourceId: string): void {
    this.selectedSourceId.set(sourceId);
  }

  onIncludeSystemAudioChange(event: Event): void {
    const input = event.target as HTMLInputElement;

    this.includeSystemAudio.set(!!input.checked);
  }

  confirmSelection(): void {
    const sourceId = this.selectedSourceId();

    if (!sourceId) {
      return;
    }

    this.picker.confirm(sourceId, this.includeSystemAudio());
  }

  cancel(): void {
    this.picker.cancel();
  }

  private getTabSources(tab: ScreenShareSourceKind): ScreenShareSourceOption[] {
    return tab === 'screen' ? this.screenSources() : this.windowSources();
  }
}
