import { Injectable } from '@angular/core';
import { InputDTO, UISettingsDTO, QueryTokenDTO, OrderByDTO } from '@swagger/cat';
import { Filter } from '../models/filter.model';
import { FilterItemMapping } from './filter-item.mapping';
import { FilterItem } from '../models/filter-item.model';

@Injectable({ providedIn: 'root' })
export class FilterMapping {
  constructor(private filterItemMapping: FilterItemMapping) {}

  fromInputDto(input: InputDTO): Filter {
    let items: FilterItem[] = [];
    let max: number;

    if (input.options != null && input.options.values) {
      (max = input.options.max), (items = input.options.values.map((item) => this.filterItemMapping.fromOptionDto(item)));
    }

    if (input.value != null) {
      if (max == null) {
        const selectedValues = input.value.split(';');
        for (const selected of selectedValues) {
          const idx = items.findIndex((f) => f.id === selected);
          if (idx >= 0) {
            items[idx].selected = true;
          }
        }
      } else {
        const idx = items.findIndex((f) => f.id === input.value);
        if (idx >= 0) {
          items[idx].selected = true;
        }
      }
    }

    return {
      expanded: false,
      id: input.key,
      name: input.label,
      max,
      items,
    };
  }

  fromUiSettingsDto(settings: UISettingsDTO): Filter[] {
    const filters: Filter[] = [];

    const filteredSettings = settings.filter
      .filter((f) => f.type === 2 && f.options)
      .filter((f) => f.options && Array.isArray(f.options.values));

    for (const filter of filteredSettings) {
      filters.push(this.fromInputDto(filter));
    }

    if (Array.isArray(settings.orderBy) && settings.orderBy.length > 0) {
      filters.push({
        expanded: false,
        id: 'orderBy',
        max: 1,
        name: 'Sortierung',
        items: settings.orderBy.map((o) => this.filterItemMapping.fromOrderByDto(o)),
      });
    }

    return filters;
  }

  toQueryTokenDto(target: QueryTokenDTO, source: Filter[], archive: boolean, negative: boolean) {
    const orderBy = source.find((f) => f.id === 'orderBy');
    if (orderBy != null) {
      target.orderBy = orderBy.items
        .filter((i) => i.selected)
        .map(
          (m) =>
            ({
              by: m.id,
              desc: m.desc,
            } as OrderByDTO)
        );
    }

    const filter = source.filter((f) => f.id !== 'orderBy').filter((f) => f.items && f.items.some((s) => s.selected));
    if (Array.isArray(filter)) {
      const kvps = filter.map((fil) => {
        const key = fil.id;
        const value = fil.items
          .filter((f) => f.selected)
          .map((f) => (negative && fil.id !== 'stock' ? '!' + f.id : f.id))
          .join(';');
        return [key, value];
      });

      if (kvps && kvps.length > 0) {
        target.filter = {};
        for (const kvp of kvps) {
          target.filter[kvp[0]] = kvp[1];
        }
      }
    }

    if (archive) {
      if (!target.filter) {
        target.filter = {};
      }
      target.filter['cattype'] = '2';
    }

    return target;
  }
}
