import {
  Component,
  ChangeDetectionStrategy,
  ContentChildren,
  QueryList,
  Input,
  HostBinding,
  forwardRef,
  ChangeDetectorRef,
  OnInit,
  AfterContentInit,
  OnDestroy,
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subscription } from 'rxjs';
import { UiRadioButtonComponent } from './radio-button.component';

@Component({
  selector: 'ui-radio-group',
  templateUrl: 'radio-group.component.html',
  styleUrls: ['radio-group.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => UiRadioGroupComponent),
      multi: true,
    },
  ],
})
export class UiRadioGroupComponent implements ControlValueAccessor, AfterContentInit, OnDestroy {
  value: any;

  disabled: boolean;

  @ContentChildren(UiRadioButtonComponent, { read: UiRadioButtonComponent, descendants: true })
  radios: QueryList<UiRadioButtonComponent>;

  private onChange = (v) => {};
  private onTouched = () => {};

  private subscription = new Subscription();

  constructor(private cdr: ChangeDetectorRef) {}

  ngAfterContentInit() {
    this.registerRadioButtonOnChange();
    this.updateRadios();

    this.subscription.add(
      this.radios.changes.subscribe(() => {
        this.registerRadioButtonOnChange();
        this.updateRadios();
      })
    );
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }

  private registerRadioButtonOnChange() {
    this.radios.forEach((radio) => radio.registerOnChange((v) => this.selectValue(v)));
  }

  writeValue(obj: any): void {
    this.selectValue(obj);
  }

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

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

  setDisabledState?(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }

  selectValue(value: any) {
    this.value = value;
    this.onChange(this.value);
    this.onTouched();
    this.updateRadios();
    this.cdr.markForCheck();
  }

  updateRadios() {
    this.radios?.forEach((radio) => radio.valueChanged(this.value));
  }
}
