import { ChangeDetectionStrategy, Component, HostListener, Input, ViewChild } from '@angular/core';
import { debounceTime, distinctUntilChanged, map, tap } from 'rxjs/operators';
import { BehaviorSubject } from 'rxjs';
import { SpotlightSearchAction } from '@components/spotlight-search/spotlight-search-action';
import { MatMenuTrigger } from '@angular/material/menu';

@Component({
    selector: 'redaction-spotlight-search [actions]',
    templateUrl: './spotlight-search.component.html',
    styleUrls: ['./spotlight-search.component.scss'],
    changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SpotlightSearchComponent {
    @Input() actions: readonly SpotlightSearchAction[];
    @Input() placeholder?: string;
    readonly valueChanges$ = new BehaviorSubject<string>('');
    @ViewChild(MatMenuTrigger) private readonly _menuTrigger!: MatMenuTrigger;
    readonly showActions$ = this.valueChanges$.pipe(
        debounceTime(300),
        map(value => value !== ''),
        tap(show => (show ? this._menuTrigger.openMenu() : this._menuTrigger.closeMenu())),
    );
    private readonly _currentActionIdx$ = new BehaviorSubject(0);
    readonly currentActionIdx$ = this._currentActionIdx$.asObservable().pipe(distinctUntilChanged());

    get shownActions(): readonly SpotlightSearchAction[] {
        return this.actions.filter(a => !a.hide?.());
    }

    private get _currentActionIdx(): number {
        return this._currentActionIdx$.getValue();
    }

    openMenuIfValue(): void {
        const value = this.valueChanges$.getValue();
        if (value && value !== '') {
            this._menuTrigger.openMenu();
        }
    }

    executeCurrentAction(): void {
        this.shownActions[this._currentActionIdx].action(this.valueChanges$.getValue());
    }

    @HostListener('keydown.arrowDown', ['$event'])
    @HostListener('keydown.arrowUp', ['$event'])
    handleKeyDown(event: KeyboardEvent): void {
        event.preventDefault();
    }

    @HostListener('keyup.arrowDown', ['$event'])
    handleKeyUpArrowDown(event: KeyboardEvent): void {
        this.handleKeyDown(event);
        const index = this._currentActionIdx + 1;
        this._currentActionIdx$.next(index >= this.shownActions.length ? 0 : index);
    }

    @HostListener('keyup.arrowUp', ['$event'])
    handleKeyUpArrowUp(event: KeyboardEvent): void {
        this.handleKeyDown(event);
        const index = this._currentActionIdx - 1;
        this._currentActionIdx$.next(index < 0 ? this.shownActions.length - 1 : index);
    }
}
