<template>
  <div
    class="cropper-div"
    :style="cropperDivStyle"
  >
    <img
      ref="cropper"
      class="pyxis-detail-img"
      :src="src"
    >
  </div>
</template>
<script>

import Cropper from 'cropperjs/dist/cropper.common';
import _debounce from 'lodash/debounce';
import { calculateWidthHeight } from 'Helpers/asset';

const cropperManager = {
    instance: null,
    moved: false, // flag to check whether the crop guide has moved

    /**
     * Initalize cropperjs with image
     * @param {Image} img
     * @param {Function} onCrop,
     * @param {Object} config - Cropper configuration
     * Assign cropper
     */
    create(img, onCrop = () => {}, config = {}) {
      const debounceTime = 300,
        {
          aspectRatio,
          initial
        } = config;

      if (this.instance) {
        return;
      }

      this.instance = new Cropper(img, {
        aspectRatio,
        movable: false,
        rotatable: false,
        scalable: false,
        zoomable: false,
        background: false,
        autoCrop: !!initial,
        viewMode: 2,
        minContainerWidth: 1,
        minContainerHeight: 1,
        cropend() {
          this.moved = true;
        },
        cropstart() {
          document.activeElement.blur();
        },
        // eslint-disable-next-line func-names
        crop: _debounce(function ({ detail }) {
          // prevent autocrop
          if (!this.moved) {
            return;
          }

          const {
            x, y, width, height
          } = detail;

          // translate cropperjs to cropGuide
          onCrop({
            top: y / this.height,
            left: x / this.width,
            right: (x + width) / this.width,
            bottom: (y + height) / this.height
          });
        }, debounceTime),
        ready() {
          // translate cropGuide for cropperjs
          if (!initial) {
            return;
          }

          const {
              imageData: { width, height }
            } = this.cropper,
            { left, top, right, bottom } = initial;

          this.cropper.setCropBoxData({
            left: Math.floor(left * width),
            top: Math.floor(top * height),
            width: Math.floor((right - left) * width),
            height: Math.floor((bottom - top) * height)
          });
        }
      });
    },

    /**
     * Reset the cropped (for example when navigating away from page)
     */
    destroy() {
      if (this.instance) {
        this.instance.destroy();
        this.instance = null;
      }
    }
  },
  MAX_VALUE = 920;

export default {
  props: {
    // image src
    src: {
      type: String,
      required: true
    },
    // pass a function that listens for cropper update event
    onUpdate: {
      type: Function,
      default: () => ({})
    },
    cropGuide: {
      type: Object,
      default: () => null
    },
    aspectRatio: {
      type: Number,
      default: undefined
    },
    originalDimensions: {
      type: Object,
      default: () => ({})
    },
    cropperImageDimensions: {
      type: Object,
      default: () => ({})
    },
    masterCrop: {
      type: Object,
      default: () => null
    }
  },
  computed: {
    cropperDivStyle() {
      const { height = 0, width = 0 } = this.cropperImageDimensions || {};

      if (!(height && width)) {
        const {
          width: widthDiv,
          height: heightDiv
        } = calculateWidthHeight(this.originalDimensions, MAX_VALUE) || {};

        if (!(widthDiv && heightDiv)) {
          return {
            'max-height': `${MAX_VALUE}px`,
            'max-width': `${MAX_VALUE}px`
          };
        }

        return {
          height: `${heightDiv}px`,
          width: `${widthDiv}px`
        };
      }

      const { top = 0, left = 0, bottom = 1, right = 1 } = this.masterCrop ? this.masterCrop : {},
        cropperDivWidth = (right - left) * width,
        cropperDivHeight = (bottom - top) * height;

      return {
        height: `${cropperDivHeight}px`,
        width: `${cropperDivWidth}px`,
        top: `${top * 100}%`,
        left: `${left * 100}%`,
        position: 'relative'
      };
    }
  },
  mounted() {
    cropperManager.create(
      this.$refs.cropper,
      this.onUpdate.bind(this),
      {
        initial: this.cropGuide,
        aspectRatio: this.aspectRatio
      }
    );
  },
  destroyed() {
    cropperManager.destroy();
  }
};
</script>
<style lang="scss" scoped>
  @import "~cropperjs/dist/cropper.css";

  img {
    display: block;
    max-height: 100%;
    max-width: 100%;
  }
</style>
