import { createFeature, createReducer, on } from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { Setting } from '../../models/setting.model';
import { SettingsActions } from './settings.actions';

export interface SettingsState extends EntityState<Setting> {
  loading: boolean;
  saving: boolean;
  error: string | null;
  loaded: boolean;
}

export const settingsAdapter: EntityAdapter<Setting> = createEntityAdapter<Setting>();

const initialState: SettingsState = settingsAdapter.getInitialState({
  loading: false,
  saving: false,
  error: null,
  loaded: false,
});

export const settingsFeature = createFeature({
  name: 'settings',
  reducer: createReducer(
    initialState,
    on(SettingsActions.loadSettings, (state, action) =>
      state.loaded && !action.forceReload ? state : {
        ...state,
        loading: true,
        error: null,
      }
    ),
    on(SettingsActions.loadSettingsSuccess, (state, { settings }) =>
      settingsAdapter.setAll(settings, { ...state, loading: false, loaded: true })
    ),
    on(SettingsActions.loadSettingsFailure, (state, { error }) => ({
      ...state,
      loading: false,
      error,
    })),
    on(SettingsActions.upsertSetting, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(SettingsActions.upsertSettingSuccess, (state, { setting }) =>
      settingsAdapter.upsertOne(setting, { ...state, saving: false })
    ),
    on(SettingsActions.upsertSettingFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    on(SettingsActions.deleteSetting, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(SettingsActions.deleteSettingSuccess, (state, { id }) =>
      settingsAdapter.removeOne(id, { ...state, saving: false })
    ),
    on(SettingsActions.deleteSettingFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    on(SettingsActions.clearSettingsError, (state) => ({
      ...state,
      error: null,
    }))
  ),
});

const { selectAll, selectTotal } = settingsAdapter.getSelectors(settingsFeature.selectSettingsState);

export const selectAllSettings = selectAll;
export const selectSettingsTotal = selectTotal;
export const selectSettingsLoading = settingsFeature.selectLoading;
export const selectSettingsSaving = settingsFeature.selectSaving;
export const selectSettingsError = settingsFeature.selectError;
export const selectSettingsLoaded = settingsFeature.selectLoaded;
