import {
  AfterViewInit,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  EventEmitter,
  Injector,
  Input,
  OnChanges,
  Output,
} from '@angular/core';
import { ControlValueAccessor, NgControl, NG_VALUE_ACCESSOR } from '@angular/forms';
import { uuid } from '@utils/uuid.util';
import { RadiobuttonGroupDirection } from './radiobutton-group-direction.enum';
import { Radiobutton } from './radiobutton.model';

/**
 * A radiobutton-group component.
 *
 * ## Usage
 * ``import {UiRadiobuttonGroupModule} from '@ui/radiobutton-group/radiobutton-group.module';``
 */
@Component({
  selector: 'ui-radiobutton-group',
  templateUrl: './radiobutton-group.component.html',
  styleUrls: ['./radiobutton-group.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: RadiobuttonGroupComponent,
      multi: true,
    },
  ],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RadiobuttonGroupComponent implements ControlValueAccessor, AfterViewInit, OnChanges {
  @Input() uiDirection: RadiobuttonGroupDirection;
  @Input() uiInvalid: boolean;
  @Input() uiValidationMessage: string;
  @Input() uiRadiobuttons: Radiobutton[];
  @Input() uiBooleanValues: boolean;
  @Input() uiSecondary: boolean;
  @Input() uiRequired: boolean;
  @Input() uiName: string;
  @Input() uiId: string = uuid();
  @Input() uiAnnounceIfOptional: boolean;
  @Output() uiOnChange = new EventEmitter<any>();

  name: string | number;
  onTouched: () => {};
  private onChange: (value: any) => {};
  private _value: any;

  constructor(private injector: Injector, private changeDetectorRef: ChangeDetectorRef) {}

  get currentValue(): any {
    return this._value;
  }

  get radiobuttonsModifierClass(): string {
    if (this.uiDirection === RadiobuttonGroupDirection.HORIZONTAL) {
      return `ui-radiobutton-group__radiobuttons--horizontal`;
    }
    return '';
  }

  private _transformValue(value: any): any {
    return this.uiBooleanValues ? value === 'true' : value;
  }

  private get _requiredText() {
    if (this.uiRequired && !this.uiAnnounceIfOptional) {
      return ' (obligatoriskt)';
    }

    if (!this.uiRequired && this.uiAnnounceIfOptional) {
      return ' (frivilligt)';
    }

    return '';
  }

  getLabelText(label: string): string {
    return `${label}${this._requiredText}`;
  }

  ngAfterViewInit(): void {
    const ngControl: NgControl = this.injector.get(NgControl, null);
    if (ngControl) {
      this.name = this.uiName || ngControl.name;
    }
  }

  ngOnChanges(): void {
    const ngControl: NgControl = this.injector.get(NgControl, null);
    if (ngControl) {
      this.name = this.uiName || ngControl.name;
    }
  }

  checkForChange(rawValue: any): void {
    const value = this._transformValue(rawValue);
    if (this._value !== value) {
      if (this.onChange) {
        this.onChange(value);
      }
      this._value = value;
      this.uiOnChange.emit(value);
    }
  }

  writeValue(value: any): void {
    this._value = value;
    this.changeDetectorRef.detectChanges();
  }

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

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