import { State, Selector, Action, StateContext, Actions, ofAction } from '@ngxs/store';
import { LoadAutocomplete, CancelPendingAutocomplete } from '../actions/autocomplete.actions';
import { ProductService } from '../../services/product.service';
import { tap, map, takeUntil } from 'rxjs/operators';
import { AutocompleteDTO } from '@swagger/cat';
import { AutocompleteResults } from '../../models/autocomplete-results.model';
import { timer } from 'rxjs';
import { Injectable } from '@angular/core';

const AUTOCOMPLETE_MAX_ITEMS = 10;

export class AutocompleteStateModel {
  result: AutocompleteResults[];
}

@State<AutocompleteStateModel>({
  name: 'autocomplete',
  defaults: {
    result: [],
  },
})
@Injectable()
export class AutocompleteState {
  constructor(private productService: ProductService, private actions$: Actions) {}

  @Selector()
  static getAutocompleteResults(state: AutocompleteStateModel) {
    return state.result;
  }

  @Action(LoadAutocomplete)
  load(ctx: StateContext<AutocompleteStateModel>, { payload, type }: LoadAutocomplete) {
    return this.productService.complete(payload, 1, type).pipe(
      takeUntil(timer(2000)), // Use a timer instead of a timeout to prevent the stream from throwing an error
      map((items: AutocompleteDTO[]) => items.slice(0, AUTOCOMPLETE_MAX_ITEMS)),
      map(
        (items: AutocompleteDTO[]) => items && items.map((t) => <AutocompleteResults>{ display: t.display, type: t.type, query: t.query })
      ),
      takeUntil(this.actions$.pipe(ofAction(CancelPendingAutocomplete))),
      tap((result: AutocompleteResults[]) => {
        if (result) {
          ctx.patchState({ result });
        }
      })
    );
  }
}
