import { Directive, ElementRef, ChangeDetectorRef, Input, HostListener, forwardRef } from '@angular/core';
import { AbstractControl, NG_VALIDATORS, ValidationErrors, Validator } from '@angular/forms';
import { NbDynamicOverlay, NbDynamicOverlayHandler, NbPosition, NbTrigger, NbAdjustment } from '@nebular/theme';
import { PopoverMsgComponent } from '../rbj-tooltip/popover-msg/popover-msg.component';

@Directive({
  selector: 'input[ffMsg], textarea[ffMsg]',
  providers: [
    NbDynamicOverlayHandler,
    NbDynamicOverlay,
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => ForceFocusMsgDirective),
      multi: true,
    },
  ],
})
export class ForceFocusMsgDirective implements Validator {

  private dynamicOverlay: NbDynamicOverlay;
  constructor(
    private elementRef: ElementRef,
    private dynamicOverlayHandler: NbDynamicOverlayHandler,
    private cdRef: ChangeDetectorRef) { }



  private _invalidMsg: string = 'Invalid format';
  private _required: boolean = false;
  public get invalidMsg(): string {
    return this._invalidMsg;
  }
  @Input('ffMsg')
  public set invalidMsg(v: string) {
    if (this._invalidMsg != v) {
      this._invalidMsg = v;
      if (this.dynamicOverlay) this.dynamicOverlay = this.configureDynamicOverlay().rebuild();
    }
  }

  @Input('ffMsgPosition') public msgPosition: NbPosition = NbPosition.BOTTOM_END;

  @Input()
  public set required(value) {
    this._required = typeof value !== 'undefined' && value !== false;
  }


  private _invalid: boolean = false;
  public get invalid(): boolean {
    return this._invalid;
  }
  @Input() public set invalid(v: boolean) {
    if (this._invalid != v) {
      this._invalid = v;
    }
  }
  ngOnInit() {
    this.dynamicOverlayHandler
      .host(this.elementRef)
      .componentType(PopoverMsgComponent);

  }

  ngAfterViewInit() {
    this.dynamicOverlay = this.configureDynamicOverlay().build();
  }
  ngOnChange() {
    //this.dynamicOverlay = this.configureDynamicOverlay().rebuild();

  }
  ngOnDestroy() {
    this.dynamicOverlayHandler.destroy();
  }


  validate(control: AbstractControl): ValidationErrors {
    if (this.elementRef.nativeElement && this.elementRef.nativeElement.form
      && this.elementRef.nativeElement.form.className.indexOf('ng-untouched') == -1) {
      if (control.value != undefined && this._required && this.elementRef.nativeElement.value.length == 0) {

        this.dynamicOverlay = this.configureDynamicOverlay('Please fill out this field.').rebuild();
        this.invalid = true;
        this.show();
        return {
          input: {
            forceMsg: "Value Required Field.",
          },
        };
      }
    }
    this.invalid = false;

  }
  registerOnValidatorChange?(fn: () => void): void {
  }

  @HostListener('focusout')
  onFocusOut() {
    setTimeout(() => {
      if (this.invalid) {
        this.elementRef.nativeElement.focus();
      } else {
        this.hide();
      }
    }, 200);
  }

  show() {


    if (!this.dynamicOverlay) {
      this.dynamicOverlay = this.configureDynamicOverlay().rebuild();
    }

    //this.invalid = true;
    if (this.dynamicOverlay) {
      this.dynamicOverlay.show();
      this.cdRef.detectChanges();
      this.elementRef.nativeElement.focus();
    }
  }

  hide() {
    //this.invalid = false;
    if (this.dynamicOverlay) {
      this.dynamicOverlay.hide();
      this.cdRef.detectChanges();
    }
  }
  protected configureDynamicOverlay(msg: string = null) {
    return this.dynamicOverlayHandler
      .position(this.msgPosition)
      .trigger(NbTrigger.NOOP)
      .adjustment(NbAdjustment.CLOCKWISE)
      .offset(0)
      //.content(this.msgContext)
      .context({
        position: this.msgPosition,
        message: msg ? msg : this.invalidMsg
      });
  }
}
