import {
  Directive,
  ElementRef,
  EventEmitter,
  forwardRef,
  HostBinding,
  HostListener,
  Inject,
  Input,
  OnChanges,
  OnDestroy,
  OnInit,
  Output,
  Renderer2,
  SimpleChanges,
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { UiFormControlDirective } from '@ui/form-control';
import { fromEvent, Subscription } from 'rxjs';
import { DOCUMENT } from '@angular/common';

@Directive({
  selector: 'input[uiInput][type="checkbox"]',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => UiRadioInputDirective),
      multi: true,
    },
    {
      provide: UiFormControlDirective,
      useExisting: UiRadioInputDirective,
    },
  ],
  exportAs: 'uiInput',
})
export class UiRadioInputDirective extends UiFormControlDirective<any> implements ControlValueAccessor, OnChanges, OnDestroy {
  @Input()
  value: any;

  selectedValue: any;

  @Input()
  @HostBinding('attr.type')
  type: string;

  private uiInputCheckedSubscription: Subscription;

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

  get valueEmpty(): boolean {
    return false;
  }

  get checked(): boolean {
    return this.elementRef.nativeElement.checked;
  }

  constructor(private elementRef: ElementRef, private renderer: Renderer2, @Inject(DOCUMENT) private document: Document) {
    super();
  }

  private registerUiInputChecked() {
    if (this.uiInputCheckedSubscription) {
      this.uiInputCheckedSubscription.unsubscribe();
    }

    this.uiInputCheckedSubscription = fromEvent(
      this.document.querySelectorAll(`input[name=${this.name}]`),
      'uiInputChecked'
    ).subscribe(() => this.render());
  }

  ngOnChanges({ name }: SimpleChanges): void {
    if (name) {
      this.registerUiInputChecked();
    }
  }

  ngOnDestroy() {
    if (this.uiInputCheckedSubscription) {
      this.uiInputCheckedSubscription.unsubscribe();
    }
  }

  writeValue(obj: any): void {
    this.selectedValue = obj;
    this.check(this.selectedValue == 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.check(false);
  }

  focus(): void {}

  @HostListener('click')
  click(): void {
    this.check(this.type === 'radio' ? true : !this.checked);
  }

  check(check: boolean, emitEvent = true) {
    if (emitEvent) {
      this.onChange(check);
    }
    this.onTouched();
    this.render();
  }

  render() {
    if (this.value == this.selectedValue) {
      if (!this.checked) {
        this.renderer.setAttribute(this.elementRef.nativeElement, 'checked', '');
        const ele: HTMLElement = this.elementRef.nativeElement;
        ele.dispatchEvent(new Event('uiInputChecked'));
      }
    } else {
      this.renderer.removeAttribute(this.elementRef.nativeElement, 'checked');
    }
  }
}
