import { Directive, forwardRef, Input, ElementRef, HostListener, Output, EventEmitter } from '@angular/core';
import { NG_VALIDATORS, Validator, AbstractControl, ValidationErrors } from '@angular/forms';
import { UuidUtils } from '../../utilities/uuid-utils';
import { RbjTooltipService } from '../../services/rbj-tooltip.service';

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

  private uuid: string;
  private _msgShown: boolean = false;

  @Input('regexValidator') public regexExpression: string = '';
  @Input('invalidMsg') public invalidMsg: string = 'Invalid format';


  private _invalid: boolean = false;
  public get invalid(): boolean {
    return this._invalid;
  }
  @Input() public set invalid(v: boolean) {
    if (this._invalid != v) {
      this._invalid = v;
      this.invalidChange.emit(v);
    }
  }
  @Output() invalidChange = new EventEmitter<boolean>()


  private _required: boolean = false;
  public get required(): boolean {
    return this._required;
  }
  public set required(v: boolean) {
    this._required = typeof v !== 'undefined' && v !== false;

  }

  constructor(
    private elementRef: ElementRef,
    private rbjTooltipService: RbjTooltipService) { }


  public get inputText(): string {
    return this.elementRef.nativeElement.value;
  }


  validate(control: AbstractControl): ValidationErrors {

    this.hide();
    if (this.inputText && this.inputText.length > 0 &&
      !this.inputText.match(new RegExp(this.regexExpression, 'g'))) {
      this.invalid = true;
      //this.show();
      return this.createValidationError(this.inputText)
    }

    this.invalid = false;
    return null;
  }
  registerOnValidatorChange?(fn: () => void): void {

  }

  ngOnInit() {
    this.uuid = UuidUtils.generate();
  }

  ngOnDestroy() {
    this.rbjTooltipService.destroy(this.uuid);
  }

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

  show() {

    let formHasBeenTouched = this.elementRef.nativeElement.form && this.elementRef.nativeElement.form.className.indexOf('ng-touched') == -1;
    if (false == formHasBeenTouched) {
      this._msgShown = true;
      this.rbjTooltipService.show(this.elementRef, this.invalidMsg, this.uuid, 0);
    }
  }

  hide() {
    //this.isOpen = false;
    if (this._msgShown) {
      this._msgShown = false;
      this.rbjTooltipService.hide(this.uuid);
    }
  }

  private createValidationError(actualValue: string): ValidationErrors {
    return {
      mask: {
        requiredRegex: this.regexExpression,
        actualValue,
      },
    };
  }
}
