import { AfterViewInit, ChangeDetectionStrategy, Component, computed, ElementRef, HostBinding, inject, input, output, signal, ViewChild } from '@angular/core';
import * as util from '../utils/util';
import { FAST_KENDO_COMMON } from '../../app.config';
import { FastOverlayComponent } from "./fast-overlay.component";
import { WinHeightPipe } from "../pipes/win-height.pipe";
import { WinWidthPipe } from "../pipes/win-width.pipe";
import { NotifyService } from '../services/notify.service';
import { FastButtonComponent } from "./fast-button.component";
import { FastTextAreaComponent } from './fast-textarea.component';
import { FastLabelComponent } from "./fast-label.component";

type WindowType = 'basic' | 'error' | 'info';

@Component({
  selector: 'fast-window',
  imports: [FAST_KENDO_COMMON, FastOverlayComponent, WinHeightPipe, WinWidthPipe, FastButtonComponent, FastTextAreaComponent, FastLabelComponent],
  template: `
<fast-overlay [layerLevel]="layerLevel()"></fast-overlay>
<kendo-window class="
  bg-base-white-500
  dark:bg-alt-gray-500
  text-base-black-1000
  dark:text-base-white-500

  [&_.k-window-content]:p-0
  [&_.k-window-content]:flex
  [&_.k-window-content]:flex-col
  " [minHeight]="minHeight()" [minWidth]="minWidth()" [height]="height() | winHeight"
  [width]="width() | winWidth" (close)="close.emit()" [style]="hostStyles">
  <kendo-window-titlebar class="m-0 p-0 items-center justify-center border-none h-8.5"
      [class]="conditionalClasses()">
    <div class="max-w-full flex flex-row flex-grow basis-full pl-1">
      <div class="overflow-hidden flex flex-grow-0 items-start justify-center mt-0 mr-1 mb-0 ml-2">
        <fast-label class="flex-grow truncate text-lg">{{ title() }}</fast-label>
      </div>
      <div class="flex flex-grow gap-1">
        @if(type() === 'info' || type() === 'error'){
        <fast-button class="w-fit" (click)="copyInfo()">
          <kendo-svg-icon [icon]="icons.copyIcon"></kendo-svg-icon>
        </fast-button>
        }
        @if(hasRefresh()) {
          <fast-button class="w-fit" (click)="refresh.emit()">
            <kendo-svg-icon [icon]="icons.arrowRotateCcwIcon"></kendo-svg-icon>
          </fast-button>
        }
        @if(hasPrint()) {
          <fast-button class="w-fit" (click)="print.emit()">
            <kendo-svg-icon [icon]="icons.printIcon"></kendo-svg-icon>
          </fast-button>
        }
      </div>
      <div class="k-window-titlebar-actions">
        @if(type() !== 'error' && type() !== 'info' ){
          @if (hasMinMaxActions()) {
            <button kendoWindowMinimizeAction></button>
            <button kendoWindowMaximizeAction></button>
          }
          @if (hasCloseAction()) {
            <button kendoWindowRestoreAction></button>
          }
        }
        <button kendoWindowCloseAction></button>
      </div>
    </div>
  </kendo-window-titlebar>

  <div class="flex flex-col flex-grow overflow-hidden" #content [hidden]="type() !== 'basic'">
    <ng-content class="flex flex-col flex-grow"></ng-content>
  </div>
  @if (type() === 'error' || type() === 'info') {
    <div class="flex flex-grow items-center justify-center m-3">
      <fast-textarea class="flex flex-col flex-grow self-center border-1" #fastTextArea [readonly]="true" [rows]="12" [value]="textContent()"/>
    </div>
    <fast-button class="w-auto" (click)="close.emit()">OK</fast-button>
  }
</kendo-window>
  `,
  styles: `
:host { @apply absolute w-full h-full }
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class FastWindowComponent implements AfterViewInit {
  @ViewChild('content') content: ElementRef;
  @ViewChild("fastTextArea") fastTextArea: FastTextAreaComponent;

  util = util;
  icons = util.icons;

  notify = inject(NotifyService);

  type = input<WindowType>('basic');
  layerLevel = input<number>(1);
  minHeight = input<number>(350);
  minWidth = input<number>(600);
  height = input<number>(0);
  width = input<number>(0);
  title = input<string>('');
  textContent = signal<string>('');
  refresh = output();
  print = output();
  hasRefresh = util.hasOutputListener(this.refresh);
  hasPrint = util.hasOutputListener(this.print);
  hasMinMaxActions = input(true);
  hasCloseAction = input(true);

  // eslint-disable-next-line @angular-eslint/no-output-native
  close = output();

  ngAfterViewInit(): void {
    this.textContent.set(this.content?.nativeElement?.textContent || '');
  }

  conditionalClasses = computed(() => {
    const classes = [] as string[];

    classes.push(...this.getLightBaseClasses(this.type()));
    classes.push(...this.getDarkBaseClasses(this.type()));

    const conditionalClasses = this.getConditionalClassesFromArrays(classes);
    return conditionalClasses;
  });



  getConditionalClassesFromArrays(classArray: string[]): { [key: string]: boolean } {
    const classes: { [key: string]: boolean } = {};
    classArray.forEach(className => {
      classes[className] = true;
    });
    return classes;
  }

  getLightBaseClasses(type: WindowType) {
    if (type == 'basic' || type == 'info')
      return ["bg-gradient-to-b", "from-base-white-1000", "via-base-white-1000", "to-base-white-250"];

    if (type == 'error')
      return ["bg-gradient-to-b", "from-base-red-1000", "via-base-red-250", "to-base-white-250"];

  }

  getDarkBaseClasses(type: WindowType) {
    if (type == 'basic' || type == 'info')
      return ["dark:bg-gradient-to-b", "dark:from-alt-gray-1000", "dark:via-alt-gray-1000", "dark:to-alt-gray-500"];

    if (type == 'error')
      return ["dark:bg-gradient-to-b", "dark:from-alt-red-1000", "dark:via-alt-red-250", "dark:to-alt-blue-750"];
  }

  async copyInfo() {
    this.fastTextArea.textAreaElement.nativeElement.select();
    const selection = window.getSelection()?.toString();
    if (selection)
      await navigator.clipboard.writeText(selection);
    this.notify.show('copied', 'success', false, 'top');
  }

  @HostBinding('style') get hostStyles() {
    if (this.type() === 'error' || this.type() === 'info')
      return { 'z-index': 99999 };

    let zIndex: number;
    switch (this.layerLevel()) {
      case 1: zIndex = 10002; break;
      case 2: zIndex = 11002; break;
      default: zIndex = 11002 + (2 * (this.layerLevel() - 2)); break;
      // default case results in the following pattern:
      // case 3 = 11002 + (2 * (3-2)) = 11004
      // case 4 = 11002 + (2 * (4-2)) = 11006
      // case 5 = 11002 + (2 * (5-2)) = 11008
    };

    return { 'z-index': zIndex };
  }
}
