import { ActiveDescendantKeyManager } from '@angular/cdk/a11y';
import { Component, EventEmitter, HostListener, Input, OnChanges, Output, QueryList, SimpleChanges, ViewChildren } from '@angular/core';
import { BranchDTO } from '@swagger/checkout';
import { geoDistance } from '@utils/common';
import { UiBranchDropdownItemComponent } from './branch-dropdown-item.component';

@Component({
  selector: 'ui-branch-dropdown',
  templateUrl: 'branch-dropdown.component.html',
  styleUrls: ['branch-dropdown.component.scss'],
})
export class UiBranchDropdownComponent implements OnChanges {
  private _keyManager: ActiveDescendantKeyManager<UiBranchDropdownItemComponent>;

  @ViewChildren(UiBranchDropdownItemComponent) set fn(items: QueryList<UiBranchDropdownItemComponent>) {
    if (!this._keyManager) {
      this._keyManager = new ActiveDescendantKeyManager(items).withWrap(true);
    }
    this._keyManager?.setFirstItemActive();
  }

  @Input()
  branches: BranchDTO[];

  filteredBranches: BranchDTO[];

  @Input()
  selected: string;

  @Output()
  selectBranch = new EventEmitter<BranchDTO>();

  searchFilter: string;
  isOpen = false;

  get activeItem() {
    return this._keyManager?.activeItem;
  }

  constructor() {}

  open() {
    this.isOpen = true;

    this.searchFilter = undefined;
    this.setFilteredBranches();
  }

  ngOnChanges({ branches }: SimpleChanges): void {
    if (branches) {
      this.setFilteredBranches();
    }
  }

  @HostListener('keydown', ['$event'])
  onKeydown(event: KeyboardEvent) {
    if (this.isOpen) {
      switch (event.key) {
        case 'Enter':
          this.setBranch(this.activeItem.branch);
          this._keyManager.setActiveItem(-1);
          event.preventDefault();
          break;
        case 'Escape':
          this.isOpen = false;
          break;
        case 'ArrowUp':
        case 'ArrowDown':
          this._keyManager.onKeydown(event);
          this.activeItem?.scrollIntoView();
          break;
      }
    }
  }

  setBranch(branch: BranchDTO) {
    this.isOpen = false;
    this.selectBranch.emit(branch);
  }

  filter(event: string) {
    this.setFilteredBranches(event);
  }

  setFilteredBranches(filterValue?: string) {
    const branches = [...this.branches];
    const currentBranch = branches.find((b) => b.name === this.selected);
    if (!!filterValue) {
      const filterResult = branches.filter((b) => {
        const name = b.name.toLowerCase();
        const zipCode = b.address?.zipCode;
        const city = b.address?.city?.toLowerCase();
        if (!zipCode || !city) {
          return name.indexOf(filterValue.toLowerCase()) >= 0;
        } else {
          return (
            name.indexOf(filterValue.toLowerCase()) >= 0 ||
            zipCode.indexOf(filterValue) >= 0 ||
            city.indexOf(filterValue.toLowerCase()) >= 0
          );
        }
      });
      this.filteredBranches = filterResult.sort((a: BranchDTO, b: BranchDTO) => this.branchSorterFn(a, b, currentBranch));
    } else {
      const filterResult = branches;
      this.filteredBranches = filterResult.sort((a: BranchDTO, b: BranchDTO) => this.branchSorterFn(a, b, currentBranch));
    }
  }

  private branchSorterFn(a: BranchDTO, b: BranchDTO, userBranch: BranchDTO) {
    return (
      geoDistance(userBranch?.address?.geoLocation, a?.address?.geoLocation) -
      geoDistance(userBranch?.address?.geoLocation, b?.address?.geoLocation)
    );
  }
}
