import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';

import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  forwardRef,
  HostBinding,
  HostListener,
  Input,
  ViewEncapsulation,
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { IconComponent } from '@shared/components/icon';

@Component({
  selector: 'shared-checkbox',
  templateUrl: 'checkbox.component.html',
  styleUrls: ['checkbox.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CheckboxComponent),
      multi: true,
    },
  ],
  imports: [IconComponent],
  encapsulation: ViewEncapsulation.None,
  host: {
    class: 'shared-checkbox',
  },
})
export class CheckboxComponent implements ControlValueAccessor {
  private selected: any;
  @Input() value: any = true;
  @Input() showCheckbox = true;

  @HostBinding('class.disabled') @Input() disabled: boolean;

  @HostBinding('class.checked') get checked(): boolean {
    return this.selected == this.value;
  }

  @Input()
  name: string;

  private _readonly = false;

  @Input()
  @HostBinding('attr.readonly')
  get readonly(): BooleanInput {
    return this._readonly;
  }
  set readonly(value: BooleanInput) {
    this._readonly = coerceBooleanProperty(value);
  }

  private onChange = (v: any) => {};
  private onChangeForParent = (checked: boolean, value: any) => {};
  private onTouched = () => {};

  constructor(private cdr: ChangeDetectorRef) {}

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

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

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

  registerOnChangeForParent(fn: (checked: boolean, value: any) => void) {
    this.onChangeForParent = fn;
  }

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

  selectValue(value: any, emitEvent = true) {
    this.selected = value;

    if (emitEvent) {
      this.onChange(this.value);
      this.onChangeForParent(this.checked, this.value);
      this.onTouched();
    }

    this.cdr.markForCheck();
  }

  @HostListener('click')
  @HostListener('keydown.enter')
  @HostListener('keydown.space')
  select() {
    if (this.disabled || this.readonly) {
      return;
    }
    if (this.checked) {
      this.selected = undefined;
    } else {
      this.selected = this.value;
    }

    this.onChange(this.checked ? this.value : undefined);
    this.onChangeForParent(this.checked, this.value);

    this.onTouched();
    this.cdr.markForCheck();
  }
}
