import React from 'react';
import {CloudinaryImage} from "@cloudinary/base/assets/CloudinaryImage";

import {
  HtmlLayer,
  plugins
} from '../../html/dist'

interface ImgProps {
  transformation: CloudinaryImage,
  plugins?: plugins,
  [x: string]: any
}

/**
 * @mixin ReactSDK
 * @description This is our React SDK. The objective of this library is to render images
 * as is or with our plugins
 *
 * @example
 * <caption>
 *  Please note that the order of the plugins is important. See home for more details.
 * </caption>
 * // Example
 * import {CloudinaryImage} from "@cloudinary/base/assets/CloudinaryImage";
 * import {
 *  CldImg,
 *  accessibility,
 *  responsive,
 *  lazyload,
 *  placeholder
 * } from '@cloudinary/react';
 *
 * const App = () => {
 *   let img = new CloudinaryImage()
 *     .setConfig({
 *        cloud: {
 *          cloudName: 'demo'
 *        }})
 *     .setPublicID('sample');
 *
 *   return (
 *      <div>
 *         <div style={{height: "1000px"}}/>
 *         <CldImg
 *            transformation={img}
 *            plugins={[lazyload(), responsive(100), placeholder()]}
 *         />
 *      </div>
 *   )
 * };
 *
 *
 *
 *
 *
 */



/**
 * @memberOf ReactSDK
 * @type {Component}
 * @description The Cloudinary image component
 * @prop {CloudinaryImage} transformation Generated by @cloudinary/base
 * @prop {plugins} plugins Advanced image component plugins accessibility(), responsive(), lazyload(), placeholder()
 */
class CldImg extends React.Component <ImgProps> {
  imageRef: React.RefObject<HTMLImageElement>;
  htmlLayerInstance: HtmlLayer;

  constructor(props: ImgProps) {
    super(props);
    this.imageRef = React.createRef();
  }

  /**
   * On mount creates a new HTMLLayer instance and initialises with ref to img element,
   * user generated cloudinaryImage and the plugins to be used
   */
  componentDidMount() {
    this.htmlLayerInstance = new HtmlLayer(
      this.imageRef.current,
      this.props.transformation,
      this.props.plugins,
    )
  }

  /**
   * On update we cancel running plugins and update image instance with the state of user
   * cloudinaryImage and the state of plugins
   */
  componentDidUpdate() {
    this.htmlLayerInstance.cancelCurrentlyRunningPlugins();
    // call html layer to update the dom again with plugins and reset toBeCanceled
    this.htmlLayerInstance.update(this.props.transformation, this.props.plugins)
  }

  /**
   * On unmount we cancel the currently running plugins
   */
  componentWillUnmount() {
    // safely cancel running events on unmount
    this.htmlLayerInstance.cancelCurrentlyRunningPlugins()
  }

  render() {
    const {
      transformation,
      plugins,
      ...otherProps // Assume any other props are for the base element
    } = this.props;
    return <img {...otherProps} ref={this.imageRef}/>
  }
}

export {CldImg};