import {Component, OnInit} from '@angular/core';
import {HeaderComponent} from "@header/header.component";
import {HistoryComponent} from './history/history.component';
import {HistoryCount, HistoryService} from '@api';
import { NgClass } from '@angular/common';
import {FormsModule} from '@angular/forms';
import {catchError, map, Observable} from 'rxjs';
import {SearchParams} from './search-terms';

@Component({
  selector: 'app-bans',
  imports: [
    HeaderComponent,
    HistoryComponent,
    FormsModule,
    NgClass
],
  templateUrl: './bans.component.html',
  styleUrl: './bans.component.scss'
})
export class BansComponent implements OnInit {

  constructor(public historyApi: HistoryService) {
  }

  private PAGE_SIZE: number = 10;
  private uuidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
  private actualPage: number = 0;
  private totalSearchResults: number = -1;

  public active: string = '';
  public userType: 'player' | 'staff' = "player";
  public punishmentType: 'all' | 'ban' | 'mute' | 'kick' | 'warn' = "all";
  public page: number = 0;
  public names: string[] = [];
  public finalSearchTerm: string = '';
  public searchTerm: string = '';
  public filteredNames: string[] = [];
  public pageSize = 10;
  public historyCount: HistoryCount = {
    bans: 0,
    mutes: 0,
    kicks: 0,
    warnings: 0
  }

  ngOnInit() {
    this.historyApi.getUserNames(this.userType, this.punishmentType).subscribe(names => {
      this.names = names;
    });

    this.historyApi.getTotalPunishments().subscribe(totalPunishments => {
      this.historyCount = totalPunishments;
    })

    this.pushState();

    window.addEventListener('popstate', (event) => {
      if (event.state && event.state.searchTerm !== undefined) {
        this.searchTerm = event.state.searchTerm;
        this.finalSearchTerm = event.state.searchTerm;
        this.page = event.state.page;
        this.userType = event.state.userType;
        this.punishmentType = event.state.punishmentType;
      }
    });
  }

  public getCurrentButtonId(options: 'all' | 'ban' | 'mute' | 'kick' | 'warn') {
    if (options == this.punishmentType) {
      return 'currentButton'
    }
    return null;
  }

  public getCurrentUserTypeButtonId(options: 'player' | 'staff') {
    if (options == this.userType) {
      return 'currentButton'
    }
    return null;
  }

  public filterNames() {
    if (!this.searchTerm) {
      this.filteredNames = [];
      return;
    }

    this.filteredNames = this.names.filter(name =>
      name.toLowerCase().startsWith(this.searchTerm.toLowerCase())
    ).slice(0, 10);
  }

  public selectName(name: string) {
    this.searchTerm = name;
    this.filteredNames = [];
    this.search();
  }

  public search() {
    this.pushState()
    this.finalSearchTerm = this.searchTerm;
    this.page = 0;
    if (this.finalSearchTerm.length === 0) {
      this.totalSearchResults = -1
      return
    }

    let totalSearchResultsObservable: Observable<number>;
    if (this.uuidRegex.test(this.finalSearchTerm)) {
      totalSearchResultsObservable = this.historyApi.getTotalResultsForUuidSearch(this.userType, this.punishmentType, this.finalSearchTerm);
    } else {
      totalSearchResultsObservable = this.historyApi.getTotalResultsForUserSearch(this.userType, this.punishmentType, this.finalSearchTerm);
    }
    totalSearchResultsObservable.pipe(
      map(totalSearchResults => {
        this.totalSearchResults = totalSearchResults;
      }),
      catchError(err => {
        console.error(err);
        return [];
      })
    ).subscribe();
  }

  public changeUserType(type: 'player' | 'staff') {
    this.pushState();
    this.userType = type;
    this.page = 0;
    this.finalSearchTerm = '';
    this.searchTerm = '';
    this.filteredNames = [];
  }

  public changeHistoryPunishment(type: 'all' | 'ban' | 'mute' | 'kick' | 'warn') {
    this.pushState();
    this.punishmentType = type;
    this.page = 0;
  }

  public nextPage() {
    if (this.page === this.getMaxPage()) {
      return;
    }
    this.setPage(this.page + 1)
  }

  public previousPage() {
    if (this.page === 0) {
      return;
    }
    this.setPage(this.page - 1)
  }

  public setPage(page: number) {
    if (this.actualPage !== this.page) {
      console.warn('Changing page too quickly, the previous page change has not loaded yet');
      return;
    }
    this.pushState();
    this.page = page
  }

  private pushState() {
    const state = {
      searchTerm: this.searchTerm,
      page: this.page,
      userType: this.userType,
      punishmentType: this.punishmentType
    };
    const title = 'Altitude Bans';
    const url = window.location.href;
    window.history.pushState(state, title, url);
  }

  public getMaxPage() {
    const all = this.historyCount.bans + this.historyCount.mutes + this.historyCount.warnings;
    if (this.finalSearchTerm.length !== 0) {
      return Math.floor(this.totalSearchResults / this.PAGE_SIZE);
    }
    switch (this.punishmentType) {
      case 'all':
        return Math.floor(all / this.PAGE_SIZE);
      case 'ban':
        return Math.floor(this.historyCount.bans / this.PAGE_SIZE);
      case 'mute':
        return Math.floor(this.historyCount.mutes / this.PAGE_SIZE);
      case 'kick':
        return Math.floor(this.historyCount.kicks / this.PAGE_SIZE);
      case 'warn':
        return Math.floor(this.historyCount.warnings / this.PAGE_SIZE);
      default:
        return 0;
    }
  }

  public buttonActive(compare: number): boolean {
    if (compare !== 0 && this.pageSize < this.PAGE_SIZE) {
      return false;
    }
    return this.page !== compare;
  }

  public updatePageSize(pageSize: number) {
    if (pageSize < 0) {
      return;
    } else {
      this.pageSize = pageSize;
      this.actualPage = this.page;
    }
  }

  public setSearch(searchParams: SearchParams) {
    this.userType = searchParams.userType
    this.searchTerm = searchParams.searchTerm
    this.punishmentType = searchParams.punishmentType
    this.search();
  }
}
