import {
  Component,
  ChangeDetectionStrategy,
  Input,
  ContentChild,
  ViewEncapsulation,
  ChangeDetectorRef,
  OnDestroy,
  AfterContentInit,
  inject,
} from '@angular/core';
import { NgControl } from '@angular/forms';
import { EmptyControl } from './empty-control';
import { FirstErrorPipe } from './first-error.pipe';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';

@Component({
  selector: 'shared-form-control',
  templateUrl: 'form-control.component.html',
  styleUrls: ['form-control.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  host: { 'class': 'shared-form-control', '[attr.label]': 'label' },
  imports: [FirstErrorPipe],
})
export class FormControlComponent implements OnDestroy, AfterContentInit {
  @Input()
  label: string;

  @ContentChild(NgControl, { static: true })
  controlDirective: NgControl;

  private _cdr = inject(ChangeDetectorRef);

  get control() {
    return this.controlDirective.control;
  }

  required = false;

  get displayLabel() {
    return (
      (this.label ?? this.control?.['name'] ?? '') +
      (this.required && this._hasRequiredMark ? '*' : '')
    );
  }

  private _onDestroy$ = new Subject<void>();

  private _hasRequiredMark = true;
  @Input()
  set hasRequiredMark(value: BooleanInput) {
    this._hasRequiredMark = coerceBooleanProperty(value);
  }

  ngAfterContentInit() {
    this.checkValidator();
    this.control.statusChanges
      .pipe(takeUntil(this._onDestroy$))
      .subscribe(() => {
        this.checkValidator();
        this._cdr.markForCheck();
      });
  }

  ngOnDestroy() {
    this._onDestroy$.next();
    this._onDestroy$.complete();
  }

  checkValidator() {
    const errors = this.control?.validator?.(new EmptyControl());

    this.required = !!errors?.required;
  }
}
