export const SET_VISIBLE = 'ui/SET_VISIBLE';
export const SET_VISIBLE_WITH_COUNTER = 'ui/SET_VISIBLE_WITH_COUNTER';

export const SET_WORK_IN_PROGRESS = 'ui/SET_WORK_IN_PROGRESS';

export const CUSTOM_ERROR = 'ui/CUSTOM_ERROR';
export const DISMISS_ERROR = 'ui/DISMISS_ERROR';
export const SHOW_ALERT = 'ui/SHOW_ALERT';
export const DISMISS_ALERT = 'ui/DISMISS_ALERT';
export const CONFIGURATION_NOT_FOUND_ERROR = 'ui/CONFIGURATION_NOT_FOUND';

export const VISIBILITY_NAMES = {
    globalLoader: 'globalLoader',
};

export const COUNTER_TYPE_NAMES = [VISIBILITY_NAMES.globalLoader];

export const setVisible = (name, show) => (dispatch, getState) => {
    if (COUNTER_TYPE_NAMES.includes(name)) {
        return dispatch({
            type: SET_VISIBLE_WITH_COUNTER,
            name,
            show,
        });
    }
    if (getState().ui.visibilityMap[name] !== show) {
        return dispatch({
            type: SET_VISIBLE,
            name,
            show,
        });
    }
};

export const toggleVisible = name => (dispatch, getState) => {
    dispatch(setVisible(name, !getState().ui.visibilityMap[name]));
};

export const setWorkInProgress = (name, value) => ({
    type: SET_WORK_IN_PROGRESS,
    name,
    value,
});

export const reportError = errorMessage => ({
    type: CUSTOM_ERROR,
    error: {
        message: errorMessage,
    },
});

export const reportConfigurationNotFoundError = errorMessage => ({
    type: CONFIGURATION_NOT_FOUND_ERROR,
    error: {
        message: errorMessage,
    },
});

export const dismissError = () => ({
    type: DISMISS_ERROR,
});

export const alertMessage = message => ({
    type: SHOW_ALERT,
    message,
});

export const dismissAlert = () => ({
    type: DISMISS_ALERT,
});

/**
 * Creates a flag in the backgroundWorkMap to indicate that the process is in progress
 * Can be used for async tasks like API requests
 * @param name
 * @param action
 */
export const createAsyncTask = (name, action) => async dispatch => {
    dispatch(setWorkInProgress(name, true));
    let result;
    try {
        result = await dispatch(action);
    } finally {
        dispatch(setWorkInProgress(name, false));
    }
    return result;
};

export const withGlobalLoader = action => async dispatch => {
    dispatch(setVisible('globalLoader', true));
    let result;
    try {
        result = await dispatch(action);
    } finally {
        dispatch(setVisible('globalLoader', false));
    }
    return result;
};
