import { createDefaultReceiver, fetchDataAsync, postDataAsync } from '../Actions';
import { createAsyncTask } from '../UI/Actions';
import { getUserImagesByDesignArea } from './Selectors';
import { calculateImageBrightness } from '../../Services/DesignDataService';
import { getImageUsageInfo } from './Selectors';
import {
    getCurrentCompatibilityInfoHash,
    getSelectedDesignProductionMethod,
    isVectorizedLogoMandatory,
} from '../DesignArea/Selectors';

export const RECEIVE_GALLERY = 'imageGallery/RECEIVE_GALLERY';
export const RECEIVE_GALLERY_TAGS = 'imageGallery/RECEIVE_GALLERY_TAGS';
export const SELECT_GALLERY_TAG = 'imageGallery/SELECT_GALLERY_TAG';
export const SELECT_GALLERY_TAGS = 'imageGallery/SELECT_GALLERY_TAGS';
export const SET_SELECTED_IMAGE = 'imageGallery/SET_SELECTED_IMAGE';
export const UPDATE_IMAGE = 'imageGallery/UPDATE_IMAGE';
export const RECEIVE_IMAGE_UPLOAD_DATA = 'imageGallery/RECEIVE_IMAGE_UPLOAD_DATA';
export const WN_LOAD_IMAGES = 'imageGallery/LOAD_IMAGES';
export const WN_LOAD_TAGS = 'imageGallery/LOAD_TAGS';
export const WN_UPLOAD_IMAGE = 'imageGallery/UPLOAD_IMAGE';
export const UPDATE_UPLOAD_DELAYED = 'imageGallery/UPDATE_UPLOAD_DELAYED';

export const URL_TAGS = 'imagegalleryimage/tags';
export const URL_GALLERY = 'imagegalleryimage?&tags={tag}';
export const URL_UPLOAD = 'userimages/designer/edit';
export const DISMISS_ERROR = 'imageGallery/DISMISS_ERROR';
export const ADD_IMAGES_FROM_DESIGN_AREA = 'imageGallery/ADD_IMAGES_FROM_DESIGN_AREA';
export const ADD_GALLERY_IMAGE_TO_USER_IMAGES = 'imageGallery/ADD_GALLERY_IMAGE_TO_USER_IMAGES';
export const COMMIT_CHANGES = 'imageGallery/COMMIT_CHANGES';
export const SET_MODE = 'imageGallery/SET_MODE';

export const ImageGalleryModes = {
    add: 'add',
    edit: 'edit',
};

export const getGalleryUrlForTags = tags => {
    const tagTitles = tags
        .filter(tag => tag.checked === true)
        .map(tag => tag.title)
        .join();
    return URL_GALLERY.replace('{tag}', encodeURIComponent(tagTitles));
};

export const receiveGalleryTags = data => ({
    type: RECEIVE_GALLERY_TAGS,
    data: data,
});

export const fetchGallery = (tags = []) =>
    createAsyncTask(
        WN_LOAD_IMAGES,
        fetchDataAsync(getGalleryUrlForTags(tags), createDefaultReceiver(RECEIVE_GALLERY))
    );

export const fetchTags = () => createAsyncTask(WN_LOAD_TAGS, fetchDataAsync(URL_TAGS, receiveGalleryTags));

export const selectTag = tag => dispatch => {
    dispatch({
        type: SELECT_GALLERY_TAG,
        tag,
    });
    return dispatch(fetchGallery(tag));
};

export const selectTags = tags => dispatch => {
    dispatch({
        type: SELECT_GALLERY_TAGS,
        tags,
    });
    return dispatch(fetchGallery(tags));
};

export const setSelectedImageByIdentifier = identifier => ({
    type: SET_SELECTED_IMAGE,
    identifier,
});

export const setSelectedImageData = imageData => ({
    type: SET_SELECTED_IMAGE,
    imageData,
});

export const updateImage = (identifier, imageDataPatch, immediateCommit = false) => (dispatch, getState) => {
    const imageUsageInfo = getImageUsageInfo(getState(), identifier);
    dispatch({
        type: UPDATE_IMAGE,
        identifier,
        immediateCommit,
        imageUsageInfo,
        imageDataPatch,
    });
};

export const updateUploadDelayed = uploadDelayed => ({
    type: UPDATE_UPLOAD_DELAYED,
    uploadDelayed,
});

export const uploadImage = file =>
    createAsyncTask(WN_UPLOAD_IMAGE, async (dispatch, getState) => {
        const designProductionMethod = getSelectedDesignProductionMethod(getState());
        const vectorizedLogoMandatory = isVectorizedLogoMandatory(designProductionMethod);
        const data = new FormData();
        data.append('userImage', file);
        data.append('userImageEditData', JSON.stringify({}));
        dispatch(dismissError());
        const uploadResponse = await dispatch(
            postDataAsync(
                URL_UPLOAD,
                data,
                createDefaultReceiver(RECEIVE_IMAGE_UPLOAD_DATA, {
                    vectorizedLogoMandatory,
                }),
                {
                    timeout: 180000,
                },
                {},
                {
                    useLocalErrorHandling: true,
                }
            )
        );
        return await calculateImageBrightness(uploadResponse);
    });

export const addImagesFromDesignArea = data => ({
    type: ADD_IMAGES_FROM_DESIGN_AREA,
    data: getUserImagesByDesignArea(data),
});

export const dismissError = () => (dispatch, getState) => {
    // remove the error code if it's there (eg. before new upload or when closing the popup)
    if (getState().imageGallery.lastErrorCode) {
        dispatch({
            type: DISMISS_ERROR,
        });
    }
};

/**
 *
 * @param editData
 * editData should look like this:
 *  {
 *      "fileName":"a89c9b04906d0365c620f15a7fbcc234",
 *      "operations":[
 *          {"identifier":"clipping","config":{"command":"flood","backgroundColor":"#DF151E"}}
 *      ]
 *  }
 * @param imageData
 * @param actionOptions
 */
export const editImage = (editData, imageData, actionOptions = {}) =>
    createAsyncTask(WN_UPLOAD_IMAGE, async (dispatch, getState) => {
        const designProductionMethod = getSelectedDesignProductionMethod(getState());
        const vectorizedLogoMandatory = isVectorizedLogoMandatory(designProductionMethod);
        const data = new FormData();
        const { createCopy } = editData;
        data.append('userImageEditData', JSON.stringify(editData));
        dispatch(dismissError());
        const uploadResponse = await dispatch(
            postDataAsync(
                URL_UPLOAD,
                data,
                createDefaultReceiver(RECEIVE_IMAGE_UPLOAD_DATA, {
                    imageData,
                    createCopy,
                    vectorizedLogoMandatory,
                    ...actionOptions,
                })
            )
        );
        return await calculateImageBrightness(uploadResponse);
    });

export const commitChanges = () => (dispatch, getState) => {
    const imageUsageInfo = getImageUsageInfo(getState());
    const compatibilityInfoHash = getCurrentCompatibilityInfoHash(getState());
    dispatch({
        type: COMMIT_CHANGES,
        imageUsageInfo,
        compatibilityInfoHash,
    });
};

export const addGalleryImageToUserImages = (
    imageUrl,
    thumbUrl,
    fileName,
    vectorizeColorsMap,
    svgImageSize
) => (dispatch, getState) => {
    const compatibilityInfoHash = getCurrentCompatibilityInfoHash(getState());
    return dispatch({
        type: ADD_GALLERY_IMAGE_TO_USER_IMAGES,
        imageUrl,
        thumbUrl,
        fileName,
        vectorizeColorsMap,
        compatibilityInfoHash,
        svgImageSize,
    });
};

export const setModeToAdd = () => ({
    type: SET_MODE,
    mode: ImageGalleryModes.add,
});

export const setModeToEdit = () => ({
    type: SET_MODE,
    mode: ImageGalleryModes.edit,
});
