import { AfterViewInit, Component, ElementRef, NgZone, OnDestroy, ViewChild } from '@angular/core';
import { recentSales, type Sale } from '../data/recent-sales';

declare global {
  interface Window {
    wijmo?: any;
  }
}

@Component({
  selector: 'app-flexgrid-demo',
  standalone: true,
  styleUrl: './flexgrid-demo.css',
  templateUrl: './flexgrid-demo.html'
})
export class FlexGridDemoComponent implements AfterViewInit, OnDestroy {
  @ViewChild('gridHost') private readonly gridHost?: ElementRef<HTMLDivElement>;
  @ViewChild('searchHost') private readonly searchHost?: ElementRef<HTMLDivElement>;

  readonly filterColumns = ['country', 'soldBy', 'client', 'description', 'value', 'itemCount'];

  salesView?: any;
  status = 'Loading Wijmo';

  private flex?: any;
  private filter?: any;
  private search?: any;
  private setupTimer?: number;

  constructor(private readonly zone: NgZone) {}

  ngAfterViewInit(): void {
    this.setupTimer = window.setTimeout(() => this.initializeGrid());
  }

  ngOnDestroy(): void {
    if (this.setupTimer) {
      window.clearTimeout(this.setupTimer);
    }

    this.search?.dispose?.();
    this.filter?.dispose?.();
    this.flex?.dispose?.();
  }

  private initializeGrid(): void {
    const wijmo = window.wijmo;
    const gridHost = this.gridHost?.nativeElement;
    const searchHost = this.searchHost?.nativeElement;

    if (!wijmo?.CollectionView || !wijmo?.grid?.FlexGrid || !wijmo?.grid?.filter?.FlexGridFilter || !wijmo?.grid?.search?.FlexGridSearch) {
      this.setStatus('Wijmo libraries were not loaded');
      return;
    }

    if (!gridHost || !searchHost) {
      this.setStatus('Grid host was not found');
      return;
    }

    const sales: Sale[] = recentSales.map((sale) => ({ ...sale }));

    this.salesView = new wijmo.CollectionView(
      sales,
      {
        pageSize: 5,
        trackChanges: true
      }
    );

    this.salesView.collectionChanged.addHandler(() => {
      this.zone.run(() => undefined);
    });

    this.flex = new wijmo.grid.FlexGrid(gridHost, {
      itemsSource: this.salesView,
      autoGenerateColumns: false,
      autoRowHeights: true,
      columns: [
        { header: 'ID', binding: 'id', width: 64, isReadOnly: true },
        { header: 'Client', binding: 'client', width: 180, allowSorting: false, allowDragging: false },
        { header: 'Description', binding: 'description', width: '2*', minWidth: 260, wordWrap: true },
        { header: 'Value', binding: 'value', format: 'n2', width: 120 },
        { header: 'Quantity', binding: 'itemCount', format: 'n0', width: 104 },
        { header: 'Sold By', binding: 'soldBy', width: 112 },
        { header: 'Country', binding: 'country', width: 112 }
      ]
    });

    this.filter = new wijmo.grid.filter.FlexGridFilter(this.flex, {
      filterColumns: this.filterColumns,
      showSortButtons: true
    });

    this.search = new wijmo.grid.search.FlexGridSearch(searchHost, {
      grid: this.flex,
      delay: 250,
      placeholder: 'Client, country, seller',
      searchAllColumns: true
    });

    this.setStatus('Ready');
  }

  get pageLabel(): string {
    if (!this.salesView || this.salesView.pageCount < 1) {
      return 'Page 0 of 0';
    }

    return `Page ${this.salesView.pageIndex + 1} of ${this.salesView.pageCount}`;
  }

  get visibleCount(): number {
    return this.salesView?.itemCount ?? recentSales.length;
  }

  load(input: HTMLInputElement): void {
    const file = input.files?.[0];
    const converter = window.wijmo?.grid?.xlsx?.FlexGridXlsxConverter;

    if (!file || !this.flex || !converter) {
      return;
    }

    this.setStatus(`Importing ${file.name}`);
    converter.loadAsync(
      this.flex,
      file,
      { includeColumnHeaders: true },
      () => this.setStatus(`Imported ${file.name}`),
      (reason: unknown) => this.setStatus(`Import failed: ${String(reason)}`)
    );
    input.value = '';
  }

  save(): void {
    const converter = window.wijmo?.grid?.xlsx?.FlexGridXlsxConverter;

    if (!this.flex || !converter) {
      return;
    }

    this.setStatus('Exporting FlexGrid.xlsx');
    converter.saveAsync(
      this.flex,
      {
        includeColumnHeaders: true,
        includeStyles: false,
        sheetName: 'Recent Sales'
      },
      'FlexGrid.xlsx',
      () => this.setStatus('Exported FlexGrid.xlsx'),
      (reason: unknown) => this.setStatus(`Export failed: ${String(reason)}`)
    );
  }

  previousPage(): void {
    this.salesView?.moveToPreviousPage();
  }

  nextPage(): void {
    this.salesView?.moveToNextPage();
  }

  private setStatus(message: string): void {
    this.zone.run(() => {
      this.status = message;
    });
  }
}
