import {createSelector} from 'reselect';
import {applyMiddleware, createStore as _createStore} from 'redux';
import {composeWithDevTools} from 'redux-devtools-extension';
import thunkMiddleware from 'redux-thunk';
import {createLogger} from 'redux-logger';
import promiseMiddleware from 'redux-promise-middleware';
import {persistCombineReducers, persistStore} from 'redux-persist';
import storage from 'redux-persist/lib/storage';

export {PersistGate} from 'redux-persist/lib/integration/react';

export const ALL_PAGES = -1;
export const AVAILABLE_PER_PAGE = [5, 10, 25, 50, ALL_PAGES];
export const LOAD = 'LOAD';
export const LOAD_SUCCESS = 'LOAD_SUCCESS';
export const LOAD_ERROR = 'LOAD_ERROR';
export const SORT = 'SORT';
export const FILTER = 'FILTER';
export const PAGINATION = 'PAGINATION';
export const PARAMS = 'PARAMS';

export const createRegExp = createSelector(
    filter => filter,
    filter =>
        new RegExp(
            '(' +
                filter
                    .split(' ')
                    .map(escapeRegExp)
                    .join('|') +
                ')',
            'igm'
        )
);

export const filterStr = (str, filter) => {
    return createRegExp(filter).test(str);
};

export const escapeRegExp = function(s) {
    return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
};

export const createStore = ({
    initialState = undefined,
    reducer = null,
    reducers = null,
    keysToPersist = [],
    storagePrefix = 'wmc',
    promiseTypeSuffixes = ['REQUEST', 'SUCCESS', 'ERROR'],
    collapseLogs = true,
    middlewares = []
}) => {
    if (!reducer && !reducers) {
        throw new Error('Neither reducer nor reducers were provided');
    }
    if (reducer && reducers) {
        throw new Error(
            'Both reducer and reducers were provided, you need to pick one or the other'
        );
    }

    if (reducers) {
        reducer = persistCombineReducers(
            {
                debug: true,
                key: storagePrefix,
                whitelist: keysToPersist,
                storage
            },
            reducers
        );
    }

    const predefinedMiddlewares = [
        thunkMiddleware,
        promiseMiddleware({
            promiseTypeSuffixes: promiseTypeSuffixes
        }),
        createLogger({
            level: process.env.NODE_ENV !== 'production' ? 'log' : 'error',
            collapsed: (getState, action, logEntry) => !logEntry.error || collapseLogs,
            diff: true
        })
    ].concat(middlewares);

    const store = _createStore(
        reducer,
        initialState,
        composeWithDevTools(applyMiddleware(...predefinedMiddlewares))
    );

    if (!reducers) {
        return store;
    }

    const persistor = persistStore(store);

    return {
        persistor,
        store
    };
};
