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 { UiTextAreaVariation } from './textarea-variation.enum';

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

  name: string | number;

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

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

  get currentValue(): string {
    return this._value || '';
  }

  get charactersLeft(): number {
    return this.uiMaxLength - this.currentValue.length;
  }

  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: string): void {
    if (this._value !== value) {
      if (this.onChange) {
        this.onChange(value);
      }
      this._value = value;
      this.uiOnChange.emit(value);
    }
  }

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

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

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