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';

/**
 * A checkbox input. Implemented with control value accessor
 *
 * ## Usage
 * ``import {UiCheckboxModule} from '@ui/checkbox/checkbox.module';``
 */
@Component({
  selector: 'ui-checkbox',
  templateUrl: './checkbox.component.html',
  styleUrls: ['./checkbox.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: CheckboxComponent,
      multi: true,
    },
  ],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CheckboxComponent implements AfterViewInit, ControlValueAccessor, OnChanges {
  @Input() uiInvalid: boolean;
  @Input() uiValidationMessage: string;
  @Input() uiSecondary: boolean;
  @Input() uiIndeterminate: boolean = false;
  @Input() uiLabel: string = '';
  @Input() uiRequired: boolean;
  @Input() uiId: string = uuid();
  @Input() uiName: string;
  @Input() uiAnnounceIfOptional: boolean = false;
  @Output() uiOnChange: EventEmitter<boolean> = new EventEmitter();

  name: string | number;

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

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

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

  get labelText(): string {
    return `${this.uiLabel}${this._requiredText}`;
  }

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

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

    return '';
  }

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

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

  checkForChange(value: boolean): void {
    if (this._value !== !!value) {
      if (this.onChange) {
        this.onChange(!!value);
      }
      this._value = !!value;
      this.uiOnChange.emit(!!value);
    }
  }

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

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

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