import {
  Component,
  OnInit,
  Output,
  EventEmitter,
  OnDestroy,
  ChangeDetectionStrategy,
  Input,
  ViewChild,
  ElementRef,
  ViewChildren,
  QueryList,
  HostListener,
  ChangeDetectorRef,
} from '@angular/core';
import { LoadFilters } from '../../../../../../core/store/actions/filter.actions';
import { Store, Select } from '@ngxs/store';
import { Observable, Subject } from 'rxjs';
import { map, distinctUntilChanged, takeUntil, filter, tap, take } from 'rxjs/operators';
import { SharedSelectors } from 'apps/sales/src/app/core/store/selectors/shared.selectors';
import { Filter } from 'apps/sales/src/app/core/models/filter.model';
import { isNullOrUndefined } from 'util';
import { FilterType } from 'apps/sales/src/app/core/models/filter-type.enum';
import { Side } from '@libs/ui/lib/small-double-choice-switch';
import { SelectedFilterItemComponent } from '../selected-filter-item/selected-filter-item.component';
import { WindowRef } from 'apps/sales/src/app/core/services/window-ref.service';
import { FilterItem } from 'apps/sales/src/app/core/models/filter-item.model';

@Component({
  selector: 'app-filter',
  templateUrl: './filter.component.html',
  styleUrls: ['./filter.component.scss'],
})
export class FilterComponent implements OnInit, OnDestroy {
  @Select(SharedSelectors.getDropDownFilters) filterCount$: Observable<Filter[]>;
  @Select(SharedSelectors.getSelectedFilterItems) filters$: Observable<Filter[]>;
  @Output() toggle = new EventEmitter();
  @Input() selectedFilterMode: Side;
  @ViewChild('filterContainer') filterContainer: ElementRef<any>;
  @ViewChildren(SelectedFilterItemComponent) selectedFilters: QueryList<SelectedFilterItemComponent>;
  filterIndexArray$: Observable<Filter[]>;
  showMore: boolean;
  destroy$ = new Subject();
  filters: Filter[];
  checkedFilters: Filter[];
  filterCount = 0;
  filterMoreLimit = 9;

  @Output() filtersChanged = new EventEmitter();

  get filterType() {
    if (this.selectedFilterMode) {
      return this.selectedFilterMode === Side.RIGHT ? FilterType.Negative : FilterType.Default;
    }
  }

  get numberOfFilters() {
    if (this.selectedFilters) {
      return this.filterCount + this.selectedFilters.length;
    }
    return this.filterCount;
  }

  constructor(private store: Store, private windowService: WindowRef, private cdrf: ChangeDetectorRef) {}

  selectedFilters$(id: string) {
    return this.filters$.pipe(
      filter((data) => !isNullOrUndefined(data) && !isNullOrUndefined(data) && Array.isArray(data)),
      map((data) => {
        return data.filter((f) => f.id === id);
      })
    );
  }

  ngOnInit() {
    this.store.dispatch(new LoadFilters(FilterType.Full));
    this.showMore = true;
    this.filterIndexArray$ = this.filterCount$.pipe(
      takeUntil(this.destroy$),
      filter((data) => !isNullOrUndefined(data)),
      distinctUntilChanged((prev, curr) => prev && curr && prev.length === curr.length),
      tap((f: Filter[]) => {
        if (f) {
          this.filters = f;
          this.filterCount = f.length;
        }
      })
    );
    this.filters$
      .pipe(
        takeUntil(this.destroy$),
        filter((data) => !isNullOrUndefined(data) && !isNullOrUndefined(data) && Array.isArray(data))
      )
      .subscribe((data) => {
        this.checkedFilters = data;
      });

    this.windowService.windowWidth$
      .pipe(
        filter((data) => !isNullOrUndefined(data)),
        take(1)
      )
      .subscribe((width) => {
        this.showFilterLogic(width);
      });
  }

  ngOnDestroy() {
    this.destroy$.next();
  }

  itemsConfirmed() {
    if (this.numberOfFilters > this.filterMoreLimit) {
      this.showMore = true;
      this.cdrf.detectChanges();
    }
    this.filtersChanged.emit(true);
  }

  itemsDeletedConfirmed() {
    if (this.numberOfFilters - 1 <= this.filterMoreLimit) {
      this.showMore = true;
      this.cdrf.detectChanges();
    }
    this.filtersChanged.emit(true);
  }

  toggleMore() {
    this.showMore = !this.showMore;
    this.toggle.emit(this.showMore);
    this.cdrf.detectChanges();
  }

  public refreshFilters() {
    this.cdrf.detectChanges();
  }

  getSelectFilterItems(f: Filter) {
    return f.items.filter((t) => t.selected === true);
  }

  @HostListener('window:resize', ['$event'])
  onResize(event) {
    this.showFilterLogic(event.target.innerWidth);
  }

  showFilterLogic(width: number) {
    this.filterMoreLimit = 9;
    if (width > 1024) {
      this.filterMoreLimit = 12;
    }
  }

  previousFilterSelectedItemCount(index: number) {
    if (index === 0 || isNullOrUndefined(this.filters)) {
      return 0;
    }
    let selectedItems: FilterItem[] = [];

    for (let x = 0; x < index; x++) {
      const xFilter = this.filters[x];
      if (xFilter && this.checkedFilters) {
        const hasSelectedFilter = this.checkedFilters.find((f) => f.id === xFilter.id);
        if (hasSelectedFilter) {
          const xSelectedFilter = hasSelectedFilter.items.filter((t) => t.selected === true);
          selectedItems = [...selectedItems, ...xSelectedFilter.filter((t) => t.selected === true)];
        }
      }
    }

    if (!selectedItems || selectedItems.length < 1) {
      return 0;
    }
    return selectedItems.length ? selectedItems.length : 0;
  }

  getFilterCalculatedIndex(index: number) {
    const previousSelectedFilterCount = this.previousFilterSelectedItemCount(index);
    const val = previousSelectedFilterCount + index + 1;
    return val;
  }

  getFilteSelectedItemsCalculatedIndex(index: number, selectedItemIndes: number) {
    return this.previousFilterSelectedItemCount(index) + index + selectedItemIndes + 2;
  }
}
