import { Logger } from 'src/app/service/logger.service';
import { EventEmitter, Injectable } from '@angular/core';
import { BehaviorSubject, skip } from 'rxjs';
import { Filter } from 'src/app/model/graphql/filter/filter.model';
import { Sort } from 'src/app/model/graphql/filter/sort.model';
import { TranslateService } from '@ngx-translate/core';

const log = new Logger('filterService');

export type RowsPerPageOption = number | { showAll: string };

@Injectable({
  providedIn: 'root',
})
export class FilterService {
  protected useQueryParams = false;

  get rowsPerPageOptions() {
    return [10, 25, 50, { showAll: this.translate.instant('common.all') }];
  }

  filter$ = new BehaviorSubject<Filter[]>([]);
  sort$ = new BehaviorSubject<Sort[]>([]);
  skip$ = new BehaviorSubject<number>(0);
  take$ = new BehaviorSubject<RowsPerPageOption>(this.rowsPerPageOptions[0]);
  onLoad = new EventEmitter<void>();

  get param_url_key() {
    return `param_${window.location.pathname}`;
  }

  constructor(private translate: TranslateService) {
    this.skip$.pipe(skip(1)).subscribe(skip => {
      this.setLocalStorage('skip', skip);
    });
    this.take$.pipe(skip(1)).subscribe(take => {
      if (take && Object.prototype.hasOwnProperty.call(take, 'showAll')) {
        this.take$.next(0);
        return;
      }
      this.setLocalStorage('take', take);
    });
    this.sort$.pipe(skip(1)).subscribe(sort => {
      this.setLocalStorage('sort', sort);
    });
    this.filter$.pipe(skip(1)).subscribe(filter => {
      this.setLocalStorage('filter', filter);
    });
  }

  load() {
    this.onLoad.emit();
  }

  reset(args?: { withQueryParams: boolean; withHideDeleted?: boolean }) {
    log.debug('Reset', args);
    this.useQueryParams = args?.withQueryParams ?? false;
    const filterBeforeLoad = this.getLocalStorageValue('filter');

    this.skip$.next(this.getLocalStorageValue('skip') ?? 0);
    this.take$.next(this.getLocalStorageValue('take') ?? 10);
    this.sort$.next(this.getLocalStorageValue('sort') ?? []);
    this.filter$.next(this.getLocalStorageValue('filter') ?? []);

    if (args?.withHideDeleted && !filterBeforeLoad) {
      const currentFilters = this.filter$.value;
      const deletedFilterIndex = currentFilters.findIndex(
        filter => 'deleted' in filter
      );

      if (deletedFilterIndex !== -1) {
        currentFilters[deletedFilterIndex]['deleted'].equal = false;
      } else {
        currentFilters.push({ deleted: { equal: false } });
      }

      this.filter$.next(currentFilters);
    }

    this.load();
  }

  protected getLocalStorageValue(value: string) {
    const params_ls = localStorage.getItem(this.param_url_key);
    if (params_ls) {
      const storedParams = JSON.parse(params_ls);
      return storedParams[value];
    }
    return undefined;
  }

  protected setLocalStorage(key: string, value: unknown) {
    log.debug('SetLocalStorage', key, value);

    const params_ls = localStorage.getItem(this.param_url_key);
    const storedParams = params_ls ? JSON.parse(params_ls) : {};

    storedParams[key] = value;
    localStorage.setItem(this.param_url_key, JSON.stringify(storedParams));
  }
}
