import {
  Component,
  ChangeDetectionStrategy,
  Input,
  ChangeDetectorRef,
  Output,
  EventEmitter,
  OnInit,
} from '@angular/core';
import { OrderBy } from '../tree';

@Component({
  selector: 'shared-order-by-filter',
  templateUrl: 'order-by-filter.component.html',
  styleUrls: ['order-by-filter.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: false,
})
export class OrderByFilterComponent implements OnInit {
  @Input()
  orderBy: OrderBy[];

  @Input()
  groupBy?: number[] = []; // example input: [2, 1, 2] should result in: [[item, item], [item], [item, item]]

  @Output()
  selectedOrderByChange = new EventEmitter<OrderBy>();

  get orderByKeys() {
    return this.orderBy?.map((ob) => ob.label).filter((key, idx, self) => self.indexOf(key) === idx);
  }

  get groupedOrderByKeys(): Array<{ group: number; keys: string[] }> {
    let orderByKeys = this.orderByKeys; // copy
    const grouped: Array<{ group: number; keys: string[] }> = [];

    if (this.groupBy?.length > 1) {
      // group keys based on given input groupBy array structure
      for (let [outerIndex, group] of this.groupBy?.entries()) {
        let item = {
          group: outerIndex,
          keys: [],
        };

        for (let [innerIndex, key] of orderByKeys.entries()) {
          if (innerIndex < group) {
            item.keys.push(key);
          } else {
            break;
          }
        }

        // Filter already grouped keys from initial array
        orderByKeys = orderByKeys.filter((key) => !item.keys.find((itemKey) => itemKey === key));
        grouped.push(item);
      }
    } else {
      grouped.push({ group: 1, keys: this.orderByKeys });
    }
    return grouped;
  }

  get activeOrderBy() {
    return this.orderBy?.find((f) => f.selected);
  }

  constructor(private cdr: ChangeDetectorRef) {}

  ngOnInit() {
    setTimeout(() => this.cdr.markForCheck(), 0);
  }

  setActive(orderBy: string) {
    const active = this.activeOrderBy;
    const orderBys = this.orderBy?.filter((f) => f.label === orderBy);
    let next: OrderBy;

    if (orderBys?.length) {
      if (active?.label !== orderBy) {
        next = orderBys?.find((f) => !f.desc);
      } else if (!active.desc) {
        next = orderBys?.find((f) => f.desc);
      }
    }

    this.orderBy?.filter((f) => f.selected)?.forEach((f) => f.setSelected(false));

    next?.setSelected(true);

    this.selectedOrderByChange.next(next);
    this.cdr.markForCheck();
  }
}
