import {
  Component,
  OnInit,
  forwardRef,
  Input,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  EventEmitter,
  Output,
  OnChanges,
  SimpleChanges,
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Filter, SelectFilterOption } from '../../../models';
import { cloneFilter } from '../../../utils';

@Component({
  selector: 'app-filter-group',
  templateUrl: 'filter-group.component.html',
  styleUrls: ['filter-group.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => FilterGroupComponent),
      multi: true,
    },
  ],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FilterGroupComponent implements OnInit, ControlValueAccessor, OnChanges {
  @Input()
  disabled: boolean;

  @Input()
  value: Filter[];

  @Output()
  valueChanged = new EventEmitter<Filter[]>();

  @Output()
  valueGroupChanged = new EventEmitter<Filter>();

  @Input()
  selected: Filter;

  @Input() module: 'Customer' | 'Branch' = 'Branch';

  onChange: (value: Filter[]) => void;

  onTouch: (value: Filter[]) => void;

  trackByKeyOrName = (filter: Filter) => filter.key || filter.name;

  constructor(private cdr: ChangeDetectorRef) {}

  ngOnChanges({ value, selected }: SimpleChanges): void {
    if (value) {
      this.value = this.value.map(cloneFilter);
    }
    if (value || selected) {
      const selectedFilter = this.getSelectedFilter();
      if (selectedFilter) {
        this.selected = selectedFilter.filter;
      }
    }
  }

  ngOnInit() {}

  writeValue(obj: Filter[]): void {
    if (obj !== this.value) {
      this.value = obj.map(cloneFilter);
      this.cdr.markForCheck();
    }
  }

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

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

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

  emitOnChange(changedOptionGroup: SelectFilterOption[]) {
    const selected = this.getSelectedFilter();
    selected.filter.options = changedOptionGroup;

    if (typeof this.onChange === 'function') {
      this.onChange(this.value);
    }
    this.valueChanged.emit(this.value);
    this.valueGroupChanged.emit(selected.filter);
    this.cdr.markForCheck();
  }

  getSelectedFilter() {
    if (this.value && this.selected) {
      const index = this.value.findIndex((f) => this.selected.key === f.key || this.selected.name === f.name);
      const filter = this.value[index];

      return { index, filter };
    }

    return undefined;
  }
}
