
import { Component, computed, inject, input, output, TemplateRef, ViewChild } from "@angular/core";
import { ColumnComponent, FieldDataType, FilterService, KENDO_GRID } from "@progress/kendo-angular-grid";
import { FastGridDateFilterCell } from "./fast-grid-date-filter-cell.component";
import { MessageService } from "../services/message.service";
import { DateType } from "./fast-datepicker.component";
import { handleError } from "../utils/util";
import { FastNumericTextBoxComponent } from "./fast-numerictextbox.component";
import { ReactiveFormsModule } from "@angular/forms";
import { FastGridNumericFilterCell } from "./fast-grid-numeric-filter-cell.component";
import { NgTemplateOutlet } from "@angular/common";

export type GridColType = 'text' | 'num-c#' | 'num-c0' | 'num-c2' | 'num-c2-edit' | 'num-c5' | 'num-c5-edit' | 'num-d#' | 'num-d0' | 'num-d0-edit' | 'num-d2' | 'num-d2-edit' | 'num-d5' | 'num-p#' | 'num-p#*100' | DateType;

export interface TypeFormat {
  type: GridColType;
  format?: string;
}

@Component({
  selector: 'fast-grid-col',
  imports: [KENDO_GRID, FastGridDateFilterCell, FastGridNumericFilterCell, FastNumericTextBoxComponent, ReactiveFormsModule, NgTemplateOutlet],
  template: `
    <kendo-grid-column #kendoCol [editor]="editor()" [field]="field()" [title]="computedTitle()" [width]="width()" [filter]="computedFilterType()" [format]="computedFormat()" (click)="clickMethod.emit($event)" [filterable]="filterable()" [class]="class()" [hidden]="hidden()">
      @if(this.headerTemplate() !== null) {
        <ng-template #headerTemplateRef kendoGridHeaderTemplate let-column="column" let-dataItem="dataItem" let-rowIndex="rowIndex">
          <ng-container *ngTemplateOutlet="headerTemplate(); context: { $implicit: column, column, dataItem, rowIndex }" ></ng-container>
        </ng-template>
      }

      @if(this.cellTemplate() !== null) {
        <ng-template #cellTemplateRef kendoGridCellTemplate let-column="column" let-dataItem="dataItem" let-rowIndex="rowIndex">
          <ng-container *ngTemplateOutlet="cellTemplate(); context: { $implicit: column, column, dataItem, rowIndex }"></ng-container>
        </ng-template>
      }

      @if (type().includes('date-')) {
        <ng-template kendoGridFilterCellTemplate let-filter="filter" let-column="column">
          <fast-grid-date-filter-cell [field]="field()" [type]="computedDateType()" />
        </ng-template>
      }
      @else if(type() === 'num-d0-edit') {
        <ng-template kendoGridFilterCellTemplate let-filter="filter" let-column="column">
          <fast-grid-numeric-filter-cell [field]="field()" [type]="type()"/>
        </ng-template>
        <ng-template kendoGridEditTemplate let-formGroup="formGroup">
          <fast-numerictextbox [formControl]="formGroup?.controls[editFormControlName()]" [spinners]="false" [step]="0" [decimals]="0" />
        </ng-template>
      }
      @else if(type() === 'num-d2-edit') {
        <ng-template kendoGridFilterCellTemplate let-filter="filter" let-column="column">
          <fast-grid-numeric-filter-cell [field]="field()" [type]="type()"/>
        </ng-template>
        <ng-template kendoGridEditTemplate let-formGroup="formGroup">
          <fast-numerictextbox [formControl]="formGroup?.controls[editFormControlName()]" [spinners]="false" [step]="0" [decimals]="2" />
        </ng-template>
      }
      @else if(type() === 'num-c2-edit') {
        <ng-template kendoGridFilterCellTemplate let-filter="filter" let-column="column">
          <fast-grid-numeric-filter-cell [field]="field()" [type]="type()"/>
        </ng-template>
        <ng-template kendoGridEditTemplate let-formGroup="formGroup">
          <fast-numerictextbox [formControl]="formGroup?.controls[editFormControlName()]" [spinners]="false" [step]="0" [decimals]="2" />
        </ng-template>
      }
      @else if(type() === 'num-c5-edit') {
        <ng-template kendoGridFilterCellTemplate let-filter="filter" let-column="column">
          <fast-grid-numeric-filter-cell [field]="field()" [type]="type()"/>
        </ng-template>
        <ng-template kendoGridEditTemplate let-formGroup="formGroup">
          <fast-numerictextbox [formControl]="formGroup?.controls[editFormControlName()]" [spinners]="false" [step]="0" [decimals]="5" />
        </ng-template>
      }
      @else if(type().includes('num-')) {
        <ng-template kendoGridFilterCellTemplate let-filter="filter" let-column="column">
          <fast-grid-numeric-filter-cell [field]="field()" [type]="type()"/>
        </ng-template>
      }
    </kendo-grid-column>
  `,
})
export class FastGridColComponent {
  @ViewChild('kendoCol') kendoCol: ColumnComponent;
  @ViewChild('headerTemplateRef') headerTemplateRef: TemplateRef<unknown>;
  @ViewChild('cellTemplateRef') cellTemplateRef: TemplateRef<unknown>;
  @ViewChild(FastGridDateFilterCell) dateFilterCell: FastGridDateFilterCell;
  @ViewChild(FastGridNumericFilterCell) numericFilterCell: FastGridNumericFilterCell;
  messageService = inject(MessageService);

  field = input.required<string>();
  title = input<string>();
  width = input<number>();
  type = input.required<GridColType>();
  editor = input<"boolean" | "text" | "numeric" | "date">();
  editFormControlName = input<string>(null);
  clickMethod = output<unknown>();
  headerTemplate = input<TemplateRef<unknown> | null>(null);
  cellTemplate = input<TemplateRef<unknown> | null>(null);
  filterable = input<boolean>(true);
  class = input<unknown>(null);
  hidden = input<boolean>(false);

  formats: Record<GridColType, TypeFormat> = {
    'text': { type: 'text' },
    'num-c#': { type: 'num-c#', format: '{0:$#,##.#####;($#,##.#####)}' },
    'num-c0': { type: 'num-c0', format: '{0:$#,##;($#,##)}' },
    'num-c2': { type: 'num-c2', format: '{0:$#,##.00;($#,##.00)}' },
    'num-c2-edit': { type: 'num-c2-edit', format: '{0:$#,##.00;($#,##.00)}' },
    'num-c5': { type: 'num-c5', format: '{0:$#,##.00000;($#,##.00000)}' },
    'num-c5-edit': { type: 'num-c5-edit', format: '{0:$#,##.00000;($#,##.00000)}' },
    'num-d#': { type: 'num-d#', format: '{0:#,##.#####;-#,##.#####}' },
    'num-d0': { type: 'num-d0', format: '{0:#,##;-#,##}' },
    'num-d0-edit': { type: 'num-d0-edit', format: '{0:#,##;-#,##}' },
    'num-d2': { type: 'num-d2', format: '{0:#,##.00;-#,##.00}' },
    'num-d2-edit': { type: 'num-d2-edit', format: '{0:#,##.00;-#,##.00}' },
    'num-d5': { type: 'num-d5', format: '{0:#,##.00000;-#,##.00000}' },
    'num-p#': { type: 'num-p#', format: '#,.#####\\%;(#,.#####)\\%}' },
    'num-p#*100': { type: 'num-p#*100', format: '#,.#####%;(#,.#####)%' },
    'date-short': { type: 'date-short', format: '{0:M/d/yyyy}' },
    'date-month': { type: 'date-month', format: '{0:MMM yyyy}' }
  }

  computedDateType = computed(() => {
    const dateType = this.type() as DateType;
    if (dateType)
      return dateType
    else
      this.throwTypeError();
  });

  computedTitle = computed(() => {
    return this.title() ?? this.field();
  });

  computedFilterType = computed((): FieldDataType => {
    if (this.type() === 'text')
      return 'text';
    else if (this.type().includes('date-'))
      return 'date';
    else if (this.type().includes('num-'))
      return 'numeric'
    else
      this.throwTypeError();
  });

  computedFormat = computed(() => {
    if (this.type() in this.formats) {
      return this.formats[this.type()].format;
    }
    else {
      this.throwTypeError();
    }
  });

  throwTypeError() {
    handleError(`Type {${this.type()}} not implemented in fast-grid-col`, this.messageService);
  }

  public getKendoCol() {
    return this.kendoCol;
  }

  public setDateFilterService(filterService: FilterService) {
    this.dateFilterCell.setFilterService(filterService);
  }

  public setNumFilterService(filterService: FilterService) {
    this.numericFilterCell.setFilterService(filterService);
  }
}
