import { Component, ViewEncapsulation, ChangeDetectionStrategy, ChangeDetectorRef, Input, EventEmitter, Output, HostBinding, OnChanges, SimpleChanges, OnInit } from '@angular/core';
import { DisplayInfo } from '../sos-settings/sos-settings.service';
import { SosItem, SosNom, SosTransferItem } from '../models';
import * as util from '../../_shared/utils/util';
import { ControlContainer, FormArray, FormGroup, FormGroupDirective } from '@angular/forms';
import { Observable, tap } from 'rxjs';
import { ContextMenuSelectEvent, KENDO_CONTEXTMENU } from '@progress/kendo-angular-menu';
import { NgClass } from '@angular/common';
import { FAST_PAGE_COMMON, FAST_KENDO_COMMON } from '../../app.config';
import { SosCellOverlayColorsPipe } from '../pipes/sos-cell-overlay-colors.pipe';
import { SosContextItemsPipe } from '../pipes/sos-context-items.pipe';

interface ValueHistory {
  value: number;
  isModified: boolean;
}

@Component({
  selector: 'app-sos-crude-elem-combo[frozen][propName][sosItem][display][frozenColCount][activeElement][itemIdx][fontSizeStr][data][isPathEnd]',
  templateUrl: './sos-elem-combo.html',
  styleUrls: ['./sos-elem-combo.scss'],
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush,
  viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }],
  imports: [FAST_PAGE_COMMON, FAST_KENDO_COMMON, KENDO_CONTEXTMENU, NgClass, SosContextItemsPipe, SosCellOverlayColorsPipe]
})
export class SosElemComboComponent implements OnChanges, OnInit {
  @HostBinding('style.display') hostDisplay: string = 'flex';
  @HostBinding('style.order') componentOrder: number = 0;
  @Input() frozen: boolean;
  @Input() propName: keyof SosItem | keyof SosTransferItem | keyof SosNom;
  @Input() sosItem: SosItem | SosTransferItem;
  @Input() display: DisplayInfo;
  @Input() frozenColCount: number;
  @Input() activeElement: Element;
  @Input() itemIdx: number;
  @Input() fontSizeStr: string;
  @Input() data: object[];
  @Input() isPathEnd: boolean;
  @Input() textField: string = 'name';
  @Input() valueField: string = 'id';
  @Input() comboWidth: 'narrow' | 'medium' | 'wide' = 'narrow';
  @Input() isLoading: boolean = false;
  @Input() hasContextMenu: boolean = true;

  @Output() contextSelect = new EventEmitter<ContextMenuSelectEvent>();
  @Output() filterChange = new EventEmitter();

  util = util;
  popupClass: string;
  formArray: FormArray;
  formGroup: FormGroup;
  valueChanged$: Observable<number>;
  lastTwoValues: ValueHistory[] = [];
  wasValueChanged: boolean;
  sosNom: SosNom = null;
  isTransferItem = false;
  isHidden = false;
  isNomVolume = false;
  isSupplyTransfer = false;

  constructor(private ref: ChangeDetectorRef, private formGroupDirective: FormGroupDirective) {

  }

  ngOnInit(): void {
    const form = this.formGroupDirective.form;
    this.formArray = form.get('items') as FormArray;
    if (this.formArray.length > 0) {
      this.formGroup = this.formArray.at(this.itemIdx) as FormGroup;
      const valueItem: ValueHistory = { value: this.formGroup.get(this.propName).value, isModified: false };
      this.lastTwoValues.push(valueItem);

      this.valueChanged$ = this.formArray.at(this.itemIdx).get(this.propName).valueChanges.pipe(
        tap(newValue => {
          setTimeout(() => {
            let isModified = false;
            const modifiedProps: string[] = this.formGroup.get('modifiedProps').value;
            if (modifiedProps.includes(this.propName))
              isModified = true;
            this.updateLastTwoValues(newValue, isModified);
            this.wasValueChanged = true;
          }, 50);
        })
      );
    }
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (this.comboWidth === 'narrow')
      this.popupClass = 'app-sos list-narrow';
    else if (this.comboWidth === 'medium')
      this.popupClass = 'app-sos list-medium';
    else if (this.comboWidth === 'wide')
      this.popupClass = 'app-sos list-wide';

    if (changes.display)
      this.componentOrder = this.display?.order ?? 0;

    this.isSupplyTransfer = this.sosItem && 'supplyNomId' in this.sosItem && this.sosItem.transferDealId !== null;
    this.isTransferItem = this.sosItem && 'pathName' in this.sosItem ? true : false;
    this.isHidden = this.sosItem && 'isHidden' in this.sosItem ? this.sosItem.isHidden : false;
    this.isNomVolume = this.sosNom !== null;
  }

  filterChangeInternal(filter: string): void {
    this.filterChange.emit(filter);
  }

  onKeydown(event: KeyboardEvent): void {
    //Prevent default behavior of arrow keys
    if (event.key === "ArrowUp" || event.key === "ArrowDown") {
      setTimeout(() => {
        if (this.wasValueChanged) {
          const previousValue = this.lastTwoValues[0].value;
          const wasModified = this.lastTwoValues[0].isModified;
          let modifiedProps: string[] = this.formGroup.get('modifiedProps').value;
          if (!wasModified && modifiedProps.includes(this.propName))
            modifiedProps = modifiedProps.filter(x => x !== this.propName);
          this.formGroup.patchValue({ [this.propName]: previousValue, modifiedProps: modifiedProps }, { emitEvent: false });
          if (!wasModified)
            this.formGroup.get(this.propName).markAsPristine();
          this.updateLastTwoValues(previousValue, wasModified);
        }
        this.wasValueChanged = false;
      }, 100);
    }
  }

  private updateLastTwoValues(newValue: number, isModified: boolean) {
    const valueItem: ValueHistory = { value: newValue, isModified: isModified };
    this.lastTwoValues.push(valueItem);
    if (this.lastTwoValues.length > 2)
      this.lastTwoValues.shift();
  }
}
