import { Action } from '@ngrx/store';
import { type } from '../utils/type';

const CATEGORY:string = 'LoopTopic';
/**
 * For each action type in an action group, make a simple
 * enum object for all of this group's action types.
 *
 * The 'type' utility function coerces strings into string
 * literal types and runs a simple check to guarantee all
 * action types in the application are unique.
 */
export interface ILoopTopicActions {
  QUERY: string;
  ADD_SELECTED: string;
  REMOVE_SELECTED: string;
  SET_ENTRIES: string;
  SET_SELECTED: string;
}

export const ActionTypes: ILoopTopicActions = {
  QUERY:           type(`[${CATEGORY}] Query`),
  ADD_SELECTED:    type(`[${CATEGORY}] Add Selected`),
  REMOVE_SELECTED: type(`[${CATEGORY}] Remove Selected`),
  SET_ENTRIES:     type(`[${CATEGORY}] Set Entries`),
  SET_SELECTED:    type(`[${CATEGORY}] Set Selected`),
};

/**
 * Every action is comprised of at least a type and an optional
 * payload. Expressing actions as classes enables powerful
 * type checking in reducer functions.
 *
 * See Discriminated Unions: https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions
 */
export class QueryAction implements Action {
  type = ActionTypes.QUERY;

  constructor(public payload: any[]) { }
}

export class AddSelectedAction implements Action {
    type  = ActionTypes.ADD_SELECTED;

    constructor(public payload: any) { }
}

export class RemoveSelectedAction implements Action {
    type  = ActionTypes.REMOVE_SELECTED;

    constructor(public payload: any) { }
}

export class SetEntriesAction implements Action {
  type = ActionTypes.SET_ENTRIES;

  constructor(public payload: any[] = []) { }
}

export class SetSelectedAction implements Action {
    type  = ActionTypes.SET_SELECTED;

    constructor(public payload: any[]) { }
}

/**
 * Export a type alias of all actions in this action group
 * so that reducers can easily compose action types
 */
export type Actions
  = QueryAction
  | AddSelectedAction
  | RemoveSelectedAction
  | SetEntriesAction
  | SetSelectedAction;
