import get from 'lodash/get';
import find from 'lodash/find';
import isString from 'lodash/isString';
import flatten from 'lodash/flatten';
import { getConf } from '../../configuration';
import { getUrl } from '../../Utils/getUrl';
import { getConfiguration, getConfigurator } from '../Configurator/Selectors';
import { getDesignData } from '../DesignData/Reducer';
import { ImageGalleryModes } from './Actions';
import {
    areHashesCompatible,
    designProductionMethodHasEmbroideryVisualizationEffect,
    getCurrentCompatibilityInfoHash,
    getDesignProductionMethodByIdentifier,
    getSelectedDesignProductionMethod,
    isVectorizedLogoMandatory,
} from '../DesignArea/Selectors';
import isEqual from 'lodash/isEqual';

export const vectorFormats = ['ai', 'pdf', 'svg', 'eps', 'ps', 'ept'];

export const getPreviewUrlFromImageData = (preview, options = {}) => {
    const previewUrl = isString(preview) ? preview : preview.url;
    if (/^data:image/.test(previewUrl)) {
        return previewUrl;
    }
    return getUrl(previewUrl, options.host);
};

export const isEditableVectorImage = preview => {
    return preview && preview.url && (/.svg$/.test(preview.url) || /^data:image\/svg\+xml/.test(preview.url));
};

export const getUserImage = (state, identifier) => {
    const userImages = get(state, 'imageGallery.userImages', []);

    return find(userImages, { identifier });
};

export const getUserImagesByDesignArea = configuratorState => {
    const configuration = getConfiguration(configuratorState);
    const designData = get(configuration, 'designdata');
    if (!designData) {
        return null;
    }
    return flatten(
        Object.values(designData) // merge the objects into one array
            .filter(dd => !!dd.canvasData) // get the areas with existing canvas data
            .map(data => data.canvasData.objects)
    ) // get the objects array from the areas
        .filter(o => o.type === 'Image') // filter the images
        .map(object => object.imageData) // get the imageData objects from the images
        .filter(
            (imageData, idx, arr) =>
                !imageData.isPlaceHolderImage && // placeholders are not needed in the list
                // uniq by identifier
                imageData === arr.find(({ identifier }) => identifier === imageData.identifier)
        );
};

export const getImageUsageInfo = (state, imageIdentifier) => {
    if (!imageIdentifier) {
        imageIdentifier = get(state.imageGallery.selectedImage, 'identifier');
    }
    if (!imageIdentifier) {
        return {
            count: 0,
            designAreas: 0,
        };
    }

    return Object.values(getDesignData(getConfigurator(state))).reduce(
        ({ count, designAreas }, { canvasData }) => {
            const countPerArea =
                canvasData && canvasData.objects
                    ? canvasData.objects.filter(
                          ({ imageData }) => imageData && imageData.identifier === imageIdentifier
                      ).length
                    : 0;
            return {
                designAreas: designAreas + (countPerArea ? 1 : 0),
                count: count + countPerArea,
            };
        },
        {
            count: 0,
            designAreas: 0,
        }
    );
};

export const isEditMode = state => get(state, 'imageGallery.mode') === ImageGalleryModes.edit;

export const isAddMode = state => get(state, 'imageGallery.mode') === ImageGalleryModes.add;

export const isImageCompatible = (state, imageData) =>
    areHashesCompatible(imageData.compatibilityInfoHash, getCurrentCompatibilityInfoHash(state));

export const isImageReadyToBeAdded = (state, imageData) => {
    return Boolean(
        imageData &&
            isAddMode(state) &&
            isImageCompatible(state, imageData) &&
            getImageUsageInfo(state, imageData.identifier).count > 0 // make sure it's already added (add it one more time)
    );
};

export const isColorMappingCompatible = (colorPalettes, vectorizeColorsMap) => {
    if (!colorPalettes) {
        return false;
    }
    const colors = Object.values(vectorizeColorsMap);
    return (
        !colors.length ||
        !colors
            .map(({ identifier }) => JSON.parse(identifier).palette)
            .some(identifier => !find(colorPalettes, { identifier }))
    );
};

export const showVectorizeImageQuality = (imageToAnalyse, minimumPixelAmount = null) => {
    if (imageToAnalyse) {
        const pixelsInTheImage =
            get(imageToAnalyse, 'original.width', 0) * get(imageToAnalyse, 'original.height', 0);
        const hasVectorFormat =
            vectorFormats.indexOf(get(imageToAnalyse, 'original.format', '').toLowerCase()) > -1;
        const pixelsOfReference = minimumPixelAmount || getConf('vectorizeImageQuality');

        return !hasVectorFormat && pixelsInTheImage < pixelsOfReference;
    }
    return false;
};

export const isHardModified = (originalImageData, newImageData) =>
    ['operations', 'compatibilityInfoHash'].some(
        prop => !isEqual(originalImageData[prop], newImageData[prop])
    );

export const isColorPreviewCompatible = (state, image, designProductionMethodIdentifier) => {
    if (!image) {
        image = state.imageGallery.selectedImage;
    }
    const designProductionMethod = designProductionMethodIdentifier
        ? getDesignProductionMethodByIdentifier(state, designProductionMethodIdentifier)
        : getSelectedDesignProductionMethod(state);
    const colorPreviewRequired =
        designProductionMethodHasEmbroideryVisualizationEffect(designProductionMethod) ||
        isVectorizedLogoMandatory(designProductionMethod);

    const displayColorPreview = image && (!!image.gallery || !!image.displayColorPreview);
    // do not let the user to add a raster image if the production method is embroidery
    return !colorPreviewRequired || displayColorPreview || false;
};
