import { Directive, ElementRef, forwardRef, HostBinding, HostListener, Input, Renderer2 } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { UiFormControlDirective } from '@ui/form-control';

@Directive({
  selector: 'input[uiInput]:not([type=checkbox])',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => UiInputDirective),
      multi: true,
    },
    {
      provide: UiFormControlDirective,
      useExisting: UiInputDirective,
    },
  ],
  exportAs: 'uiInput',
})
export class UiInputDirective extends UiFormControlDirective<any> implements ControlValueAccessor {
  @Input()
  @HostBinding('attr.type')
  type: string;

  private currentValue: any;

  get value() {
    return this.currentValue;
  }

  get valueEmpty(): boolean {
    return !!this.value;
  }

  private onChange = (value: any) => {};

  private onTouched = () => {};

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

  writeValue(obj: any): void {
    this.setValue(obj, false);
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  setDisabledState?(isDisabled: boolean): void {
    if (isDisabled) {
      this.renderer.setAttribute(this.elementRef.nativeElement, 'disabled', '');
    } else {
      this.renderer.removeAttribute(this.elementRef.nativeElement, 'disabled');
    }
  }

  clear(): void {
    this.setValue(undefined);
  }

  focus(): void {
    setTimeout(() => {
      this.elementRef?.nativeElement?.click()?.focus();
    }, 0);
  }

  @HostListener('input', ['$event.target.value'])
  setValue(value: any, emitEvent = true) {
    if (this.value !== value) {
      this.currentValue = value;
      this.renderer.setProperty(this.elementRef.nativeElement, 'value', value || '');
      if (emitEvent) {
        this.onChange(value);
        this.onTouched();
      }
    }
  }

  @HostListener('focus')
  onFocus() {
    this.focused.emit(true);
  }

  @HostListener('blur')
  onBlur() {
    this.onTouched();
    this.focused.emit(false);
  }
}
