import { CommonModule } from '@angular/common';
import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Optional, Output, Self, ViewChild } from '@angular/core';
import { ControlValueAccessor, FormControl, FormGroup, FormsModule, NgControl, NgForm, ReactiveFormsModule } from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
import { DxButtonModule, DxDataGridModule, DxTooltipModule } from 'devextreme-angular';
import { Subscription } from 'rxjs';
import { HenselTranslateService } from '../../services/localization/hensel-translate.service';
import {
  MatAutocompleteTrigger, MatFormField
} from '../angular-material-index';
import { AngularMaterialModule } from '../angular-material.module';
import { NgxMaskDirective, NgxMaskPipe } from 'ngx-mask';
import { LocaleService } from '@app_core/services/localization/locale.service';
import { HenselValidator } from '@app_core/validators/hensel-validator.directive';
import { HenselMaskDecimalDirective } from '@app_core/directives/hensel-decimal.directive';


@Component({
  // tslint:disable-next-line: component-selector
  selector: 'hensel-input',
  templateUrl: './hensel-input.component.html',
  styleUrls: ['./hensel-input.component.scss'],
  standalone: true,
  imports: [
    CommonModule,
    AngularMaterialModule,
    FormsModule,
    ReactiveFormsModule,
    DxButtonModule,
    DxTooltipModule,
    TranslateModule,
    DxDataGridModule,
    NgxMaskDirective,
    NgxMaskPipe,
    HenselValidator,
    HenselMaskDecimalDirective
  ]
})

export class HenselInputComponent implements OnInit, AfterViewInit, OnDestroy {

  @ViewChild(MatAutocompleteTrigger) autocompleteTrigger: MatAutocompleteTrigger;
  @ViewChild('cbInput') cbInput: ElementRef;
  @ViewChild('hs_matformfield') hsMatFormField: MatFormField;
  @ViewChild('hensel_input') hsElementRef: ElementRef;

  private hsRequiredsubscription: Subscription;
  private _required: boolean;
  public get required(): boolean {
    return this._required;
  }
  @Input() public set required(value: boolean) {
    if (typeof (value) === 'string') value = value !== 'false';
    this.setRequired(value);
    this.updateParent();
  }

  private _disabled: boolean = false;
  public get disabled(): boolean {
    return this._disabled;
  }

  @Input() public set disabled(value: boolean) {
    this.setDisable(typeof (value) === 'string' ? value !== 'false' : value);
  }

  @Input() public validate: (val: any) => boolean;

  public _value: any = null;
  @Input() public set ngModel(val: any) {
    this.setValueInternally(val, true);
    this.lastValue = this._value;
  }
  public get ngModel(): any {
    return this.value;
  }

  @Output() public get value(): any {
    return this._value;
  }

  @Output() ngModelChange = new EventEmitter<any>();
  @Input() label: string;
  @Input() placeholder: string;
  @Input() width: string = '100%';
  @Input() backgroundColor: string = 'inherit';

  @Input() hint: string;
  @Input() type: string = 'text';
  @Input() displayIconFn: (comp: HenselInputComponent) => string;
  @Input() id: string = '';
  @Input() name: string = '';
  @Input() public hsClass: string = '';
  @Input() autofocus: any = false;
  @Input() maxlength: number;
  @Input() readonly: boolean;
  @Input() autocomplete: string = '';

  private _parent: NgForm = null;
  public get parent(): NgForm {
    return this._parent;
  }

  @Input()
  public set parent(value: NgForm) {
    this._parent = value ?? this._parentForm;
    this.hsRequiredsubscription?.unsubscribe();
    this.hsRequiredsubscription = this.parent?.valueChanges.subscribe(() => this.checkRequired()); //take cares about form.invalid, if the component invalid
    this.markAsTouchedDirty();
  }


  private _canClear: boolean = true;
  public get canClear(): boolean {
    return this._canClear;
  }
  @Input() public set canClear(value: boolean) {
    this._canClear = value;
  }
  @Input() public defaultValue: any;
  @Output() public focus = new EventEmitter<HenselInputComponent>();
  @Output() public blur = new EventEmitter<HenselInputComponent>();
  @Input() public tabindex: number = 0;
  @Input() public errorMessageFn: ((value: any) => string);

  private _title: string = '';
  public get title(): string {
    let resTitle = this._title;
    // if (!resTitle && this.cbInput?.nativeElement?.clientWidth < this.cbInput?.nativeElement?.scrollWidth) resTitle = this.displayFn(this._value);
    return resTitle;
  }
  @Input() public set title(value: string) {
    this._title = value;
  }

  //***** Using Mask derictive
  @Input() mask: string;
  @Input() suffix: string = '';
  @Input() prefix: string = '';
  @Input() decimalMarker: string;
  @Input() thousandSeparator: string;
  @Input() leadZero: boolean = true;
  @Input() separatorLimit: string = '0';



  //***** Using Hensel validator
  @Input() greater: number;
  @Input() notless: number;
  @Input() notgreater: number;
  @Input() less: number;

  //***** Using Hensel decimal directive
  @Input() henselDecimal: number;
  @Input() henselDecimalAllowEmpty: boolean;


  public itemsControl = new FormControl();
  public hasFocus: boolean = false;
  private _lastValue: any;
  public get lastValue(): any {
    return this._lastValue;
  }
  public set lastValue(value: any) {
    this._lastValue = value;
  }
  public showInputField: boolean = true;
  public initialised: boolean = false;

  private get formGroup(): FormGroup {
    return this.parent?.control;
  }

  public computedBackgroundColor: string;

  constructor(
    public translate: HenselTranslateService,
    public localeService: LocaleService,
    @Optional() private _parentForm?: NgForm,
    // @Self() public ngControl?: NgControl
  ) {
  }

  ngOnInit() {
    setTimeout(() => {
      if (!this.parent) this.parent = this._parent;
    }, 0);
  }

  ngAfterViewInit(): void {
    setTimeout(() => {
      this.initialised = true;
      this.computedBackgroundColor = this.getBackgroundColor(this.hsElementRef.nativeElement);
    }, 0);
  }


  private setDisable(value: boolean) {
    this._disabled = value;
    if (this.disabled) {
      this.itemsControl.disable();
    } else this.itemsControl.enable();
  }


  private setRequired(value: boolean) {
    this._required = value;
  }


  private setValueInternally(value: any, externally = false) {
    if (value === this._value) return;
    this._value = value;
    this.itemsControl.setValue(this._value);
    if (externally) this.updateParent(); //otherwise if set programatically parent form doesn't change valid status
  }


  getBackgroundColor(htmlElemet: any): string {
    const backgroundColor = window.getComputedStyle(htmlElemet, null).getPropertyValue('background-color');
    if (backgroundColor !== 'rgba(0, 0, 0, 0)' || !htmlElemet?.parentElement) return backgroundColor;
    else return this.getBackgroundColor(htmlElemet.parentElement);
  }


  checkRequired() {
    if (this.requiredError()) this.formGroup?.setErrors({ required: true });
  }

  requiredError(): boolean {
    let req = this.required;
    return !this.disabled && req !== undefined && req !== false && this.isEmpty();
  }


  public isEmpty(): boolean {
    return !this._value;
  }



  public takeFocus = () => {  //such declaration because of binding
    this.hasFocus = true;
    this.focus.emit(this);
  }


  public leaveFocus = () => {  //such declaration because of binding
    this.hasFocus = false;
    this.blur.emit(this);
  }

  public updateParent() {
    //this.formGroup?.updateValueAndValidity();
  }



  // public clickClear($event: any) {
  //   $event.stopPropagation();
  //   if (/*this.dropDownState === EN_DropDownState.Opened ||*/ this.lastFilter) {
  //     setTimeout(() => {
  //       this.itemsControl.setValue('');
  //       this.cbInput?.nativeElement?.focus(); //to call opendropdown after close drop down if minlength>0
  //     }, 300);
  //   } else {
  //     this.lastValue = this._value;
  //     if (this.defaultValue !== undefined && this.defaultValue !== null) this.setValueInternally([this.defaultValue]);
  //     else this.setValueInternally([]);
  //     this.selectionDone();
  //   }
  // }


  ngOnDestroy(): void {
    this.hsRequiredsubscription?.unsubscribe();
  }

  getIcon(): string {
    if (this.displayIconFn) return this.displayIconFn(this);
    return null;
  }

  public markAsDirty() {
    if (this.hsMatFormField?._control?.ngControl?.control) {
      this.hsMatFormField._control.ngControl.control.markAsDirty();
      this.updateParent();
    }
  }


  public markAsTouched() {
    if (this.hsMatFormField?._control?.ngControl?.control) {
      this.hsMatFormField._control.ngControl.control.markAsTouched();
      this.updateParent();
    }
  }


  public markAsTouchedDirty() {
    if (this.hsMatFormField?._control?.ngControl?.control && this.required && this.isEmpty()) {
      this.hsMatFormField._control.ngControl.control.markAsTouched();
      this.hsMatFormField._control.ngControl.control.markAsDirty();
      this.updateParent();
    }
  }

  onChange(value: any) {
    if (value === this.value) return;
    this._value = value;
    console.log('--',value);
    this.updateParent();
    this.ngModelChange.emit(value);
  }

}
