import { Directive, ElementRef, forwardRef, Input, OnDestroy, OnInit, Renderer2 } from '@angular/core';
import { NG_VALIDATORS, AbstractControl, NgModel, Validator, ValidationErrors } from '@angular/forms';
import { Subject } from 'rxjs/Subject';

@Directive({
  selector: '[inputConfirm]',
  exportAs: 'inputConfirm',
  providers: [
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => InputConfirmDirective),
      multi: true
    }
  ]
})
export class InputConfirmDirective implements OnInit, OnDestroy, Validator {
  @Input('inputConfirmDirect') direct: NgModel | NgModel[] = undefined;
  @Input('inputConfirmTarget') target: NgModel = undefined;
  private ngUnsubscribe: Subject<void> = new Subject<void>();

  constructor(private renderer: Renderer2,
              private elementRef: ElementRef) {
  }

  ngOnInit(): void {
    if (!this.direct || !this.target) {
      return;
    }

    if (Array.isArray(this.direct)) {
      this.direct.forEach((direct: NgModel): void => {
        direct.control.valueChanges.takeUntil(this.ngUnsubscribe).distinctUntilChanged().subscribe(() => {
          this.target.control.updateValueAndValidity();
        });
      });
    } else {
      this.direct.control.valueChanges.takeUntil(this.ngUnsubscribe).distinctUntilChanged().subscribe(() => {
        this.target.control.updateValueAndValidity();
      });
    }

    /*this.target.control.setValidators((control: AbstractControl): ValidationErrors | null => {
      return {confirmInvalid: true};
    });*/

    /*this.target.control.setErrors(null);*/
  }

  ngOnDestroy(): void {
    this.ngUnsubscribe.next();
    this.ngUnsubscribe.complete();
  }

  validate(control: AbstractControl): ValidationErrors | null {
    if (!this.direct || !this.target) {
      return;
    }

    if (Array.isArray(this.direct)) {
      return (this.direct.some((direct: NgModel) => direct.value !== this.target.value)) ? {confirmInvalid: true} : null;
    } else {
      return (this.direct.value !== this.target.value) ? {confirmInvalid: true} : null;
    }
  }
}
