import { Type, InjectionToken } from '@angular/core';

import {
  ActionReducer,
  MetaReducer,
  Action,
  ActionReducerMap
} from '@ngrx/store';
import * as fromRouter from '@ngrx/router-store';
import { storeFreeze } from 'ngrx-store-freeze';

import { environment } from '../../environments/environment';

import * as AccountStore from './account';
import * as MessengerStore from './messenger';
import * as SettingStore from './setting';

export interface State {
  router: fromRouter.RouterReducerState<any>;
  account: AccountStore.State;
  messenger: MessengerStore.State;
  setting: SettingStore.State;
}

/**
 * Our state is composed of a map of action reducer functions.
 * These reducer functions are called with each dispatched action
 * and the current or initial state and return a new immutable state.
 */
export const ROOT_REDUCERS = new InjectionToken<
  ActionReducerMap<State, Action>
>('Root reducers token', {
  factory: () => ({
    router: fromRouter.routerReducer,
    account: AccountStore.reducers,
    messenger: MessengerStore.reducers,
    setting: SettingStore.reducers
  })
});

export const effects: Type<any>[] = [
  ...AccountStore.effects,
  ...MessengerStore.effects,
  ...SettingStore.effects
];

export function logger(reducer: ActionReducer<State>): ActionReducer<State> {
  return (state, action) => {
    const result = reducer(state, action);
    console.groupCollapsed(action.type);
    console.log('prev state', state);
    console.log('action', action);
    console.log('next state', result);
    console.groupEnd();

    return result;
  };
}

export const metaReducers: MetaReducer<State>[] = !environment.production
  ? [logger, storeFreeze]
  : [];

export const AccountSelector = AccountStore.selectors(
  (state: State) => state.account
);

export const MessengerSelector = MessengerStore.selectors(
  (state: State) => state.messenger
);

export const SettingSelector = SettingStore.selectors(
  (state: State) => state.setting
);
