import { Component, ElementRef, input, signal, viewChild } from '@angular/core';

const MIN = 0;
const MAX = 100;
const STEP = 1;

let nextId = 0;

@Component({
  selector: '<%= selector %>',
  imports: [],
  templateUrl: './<%= dasherize(name) %>.html',
  styleUrl: './<%= dasherize(name) %>.css',
})
export class <%= classify(name) %> {
  private readonly trackRef = viewChild<ElementRef<HTMLElement>>('track');

  protected readonly instanceId = `<%= dasherize(name) %>-${nextId++}`;
  protected readonly min = MIN;
  protected readonly max = MAX;
  protected readonly value = signal(50);

  readonly label = input('Volume');

  protected handleKeydown(event: KeyboardEvent): void {
    switch (event.key) {
      case 'ArrowRight':
      case 'ArrowUp':
        event.preventDefault();
        this.setValue(this.value() + STEP);
        break;
      case 'ArrowLeft':
      case 'ArrowDown':
        event.preventDefault();
        this.setValue(this.value() - STEP);
        break;
      case 'PageUp':
        event.preventDefault();
        this.setValue(this.value() + STEP * 10);
        break;
      case 'PageDown':
        event.preventDefault();
        this.setValue(this.value() - STEP * 10);
        break;
      case 'Home':
        event.preventDefault();
        this.setValue(this.min);
        break;
      case 'End':
        event.preventDefault();
        this.setValue(this.max);
        break;
    }
  }

  protected handlePointerDown(event: PointerEvent): void {
    (event.target as HTMLElement).setPointerCapture(event.pointerId);
    this.setValueFromPointer(event);
  }

  protected handlePointerMove(event: PointerEvent): void {
    if (event.buttons !== 1) {
      return;
    }
    this.setValueFromPointer(event);
  }

  private setValueFromPointer(event: PointerEvent): void {
    const track = this.trackRef()?.nativeElement;
    if (!track) {
      return;
    }
    const rect = track.getBoundingClientRect();
    const ratio = Math.min(1, Math.max(0, (event.clientX - rect.left) / rect.width));
    this.setValue(Math.round(this.min + ratio * (this.max - this.min)));
  }

  private setValue(next: number): void {
    this.value.set(Math.min(this.max, Math.max(this.min, next)));
  }
}
