import { CommonModule } from '@angular/common';
import {
  Component,
  EventEmitter,
  Input,
  OnChanges,
  Output,
  SimpleChanges,
} from '@angular/core';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import {
  faSort,
  faSortDown,
  faSortUp,
} from '@fortawesome/free-solid-svg-icons';
import { SORT } from '../../enums/sort';
import { Header } from '../../models/header';
import { Page } from '../../models/page';
import { Result } from '../../models/result';

@Component({
  selector: 'fbi-table',
  standalone: true,
  imports: [CommonModule, FontAwesomeModule],
  templateUrl: './table.component.html',
  styleUrl: './table.component.scss',
})
export class TableComponent implements OnChanges {
  @Input() data!: Result;

  @Output() page = new EventEmitter<Page>();
  @Output() sort = new EventEmitter<Header>();

  Math = Math;
  faSortDown = faSortDown;
  faSortUp = faSortUp;
  faSort = faSort;
  SORT = SORT;
  pagesize: PageButton[] = [];
  pager: PageButton[] = [];

  ngOnChanges(changes: SimpleChanges): void {
    const data = changes['data']?.currentValue;
    if (data) {
      this.updatePageSize(data);
      this.updatePager(data);
    }
  }

  onPage(event: MouseEvent, page: number): void {
    event.stopPropagation();
    const current = this.data?.page?.page;
    const size = this.data?.page?.size;
    if (current === page) return;
    this.page.emit(new Page({ page: page, size: size }));
  }

  onPageSize(event: MouseEvent, size: number): void {
    event.stopPropagation();
    const current = this.data?.page?.size;
    if (current === size) return;

    const page = this.data?.page ?? { page: 1, size: 100 };
    const start = (page.page - 1) * page.size + 1;
    const newPage = Math.ceil(start / size);
    this.page.emit(new Page({ page: newPage, size: size }));
  }

  onSort(event: MouseEvent, header: Header): void {
    event.stopPropagation();
    this.sort.emit(header);
  }

  private updatePageSize(data: Result): void {
    const size = data.page?.size ?? 20;
    const sizes = [10, 20, 50].map(
      (i) => new PageButton({ page: i, current: i === size })
    );

    this.pagesize = sizes;
  }

  private updatePager(data: Result): void {
    const page = data.page?.page ?? 1;
    const last = Math.ceil(data.total / (data.page?.size ?? data.total));

    // get the list of pages
    const pages = [
      1,
      page + 1 > last ? page - 2 : 1,
      page - 1,
      page,
      page + 1,
      page < 3 ? 3 : last,
      last,
    ]
      // unique
      .filter((v, i, a) => a.indexOf(v) === i)
      // in range
      .filter((i) => 1 <= i && i <= last);

    const buttons = pages.map(
      (i) =>
        new PageButton({
          page: i,
          current: i === page,
        })
    );
    if (buttons.length > 2) {
      if (buttons[0].page !== buttons[1].page - 1) {
        buttons.splice(1, 0, new PageButton({ ellipsis: true }));
      }
      const length = buttons.length;
      if (buttons[length - 2].page !== buttons[length - 1].page - 1) {
        buttons.splice(length - 1, 0, new PageButton({ ellipsis: true }));
      }
    }
    this.pager = buttons;
  }
}

export class PageButton {
  page: number;
  current: boolean;
  ellipsis: boolean;

  constructor(data: Partial<PageButton>) {
    this.page = data?.page ?? -1;
    this.current = data?.current ?? false;
    this.ellipsis = data?.ellipsis ?? false;
  }
}
