import cloneDeep from 'lodash/cloneDeep'
import {CloudinaryImage} from "@cloudinary/base/assets/CloudinaryImage";
import {plugin, htmlPluginState} from "./types";
import {PLACEHOLDER_IMAGE_OPTIONS, emptyImage} from './internalConstnats';
import {placeholderMode} from './types';

/**
 * @namespace
 * @description Displays a placeholder image until the original image loads
 * @param mode {placeholderMode} can be the following modes 'vectorize' | 'pixelate' | 'blur' | 'predominant-color'
 * @return plugin
 * @example
 * <CldImg transformation={img} plugins=[(placeholder('blur'))]/>
 */
export function placeholder(mode='vectorize'): plugin{
  return placeholderPlugin.bind(null, mode);
}

/**
 * @description Placeholder plugin
 * @param mode {placeholderMode} can be the following modes 'vectorize' | 'pixelate' | 'blur' | 'predominant-color'
 * @param element {HTMLImageElement} The image element
 * @param pluginCloudinaryImage {CloudinaryImage}
 * @param htmlPluginState {htmlPluginState} holds cleanup callbacks and event subscriptions
 */
function placeholderPlugin(mode: placeholderMode, element: HTMLImageElement, pluginCloudinaryImage: CloudinaryImage, htmlPluginState: htmlPluginState): Promise<void | string> | string  {
  const placeholderTransformation = preparePlaceholderTransformation(mode, pluginCloudinaryImage);
  element.src = placeholderTransformation.toURL();

  return new Promise((resolve: any) => {
    htmlPluginState.cleanupCallbacks.push(()=>{
      element.src = emptyImage;
      resolve('canceled');
    });

    const largeImage = new Image();
    largeImage.src = pluginCloudinaryImage.toURL();
    largeImage.onload = () => {
      resolve();
    };
  });
}

/**
 * Prepares placeholder transformation by appending a placeholder-type transformation to the end of the URL
 * @param mode {placeholderMode} can be the following modes 'vectorize' | 'pixelate' | 'blur' | 'predominant-color'
 * @param pluginCloudinaryImage {CloudinaryImage}
 */
function preparePlaceholderTransformation(mode: placeholderMode, pluginCloudinaryImage: CloudinaryImage){
  const placeholderClonedImage = cloneDeep(pluginCloudinaryImage);

  if(!PLACEHOLDER_IMAGE_OPTIONS[mode]){
    mode = 'vectorize'
  }
  //appends a placeholder transformation on placeholderClonedImage
  PLACEHOLDER_IMAGE_OPTIONS[mode].actions.forEach(transformation => placeholderClonedImage.addAction(transformation));

  return placeholderClonedImage;
}