<!--
Assistant de création d'image
https://norserium.github.io/vue-advanced-cropper/
-->
<template>
    <lazy-LayoutDialog :show="true">
      <template #dialogType>{{ $t('image_assistant') }}</template>
      <template #dialogTitle>{{ $t('modif_picture') }}</template>
      <template #dialogText>
        <div class="upload">
          <v-row
            v-if="fetchState.pending"
            class="fill-height ma-0 loading"
            align="center"
            justify="center"
          >
            <v-progress-circular
              indeterminate
              color="grey lighten-1"
            ></v-progress-circular>
          </v-row>

          <div v-else >
            <div class="upload__cropper-wrapper">
              <cropper
                ref="cropper"
                class="upload__cropper"
                check-orientation
                :src="image.src"
                :default-position="{left : coordinates.left, top : coordinates.top}"
                :default-size="coordinates.width ? {width : coordinates.width, height : coordinates.height}: defaultSize"
                @change="onChange"
              />
              <div v-if="image.src" class="upload__reset-button" title="Reset Image" @click="reset()">
                <v-icon>mdi-delete</v-icon>
              </div>
            </div>
            <div class="upload__buttons-wrapper">
              <button class="upload__button" @click="$refs.file.click()">
                <input ref="file" type="file" accept="image/*" @change="loadImage($event)" />
                {{$t('upload_image')}}
              </button>
            </div>
          </div>

        </div>
      </template>
      <template #dialogBtn>
        <v-btn class="mr-4 submitBtn ot_grey ot_white--text" @click="$emit('close')">
          {{ $t('cancel') }}
        </v-btn>
        <v-btn class="mr-4 submitBtn ot_danger ot_white--text" @click="save">
          {{ $t('save') }}
        </v-btn>
      </template>
    </lazy-LayoutDialog>

</template>

<script lang="ts">
import {defineComponent, onUnmounted, Ref, ref, useContext, useFetch, watch} from '@nuxtjs/composition-api'
import { Cropper } from 'vue-advanced-cropper'
import 'vue-advanced-cropper/dist/style.css';
import {AnyJson, ApiResponse} from "~/types/interfaces";
import {useImageProvider} from "~/composables/data/useImageProvider";
import {WatchStopHandle} from "@vue/composition-api";
import {QUERY_TYPE} from "~/types/enums";
import {File} from "~/models/Core/File";
import {repositoryHelper} from "~/services/store/repository";

export default defineComponent({
  components: {
    Cropper,
  },
  props: {
    existingImageId:{
      type: Number,
      required: false
    },
    ownerId:{
      type: Number,
      required: false
    },
    field:{
      type: String,
      required: true
    }
  },
  fetchOnServer: false,
  setup (props, {emit}) {
    const {$dataProvider, $config, $dataPersister} = useContext()
    const {getOne} = useImageProvider($dataProvider, $config)

    const fileToSave = new File()
    const cropper:Ref<any> = ref(null)
    const image: Ref<AnyJson> = ref({
      id: null,
      src: null,
      file: null,
      name: null
    })
    const coordinates:Ref<AnyJson> = ref({})
    const defaultSize = ({ imageSize, visibleArea }: any) => {
      return {
        width: (visibleArea || imageSize).width,
        height: (visibleArea || imageSize).height,
      };
    }


    //Si l'id est renseigné, il faut récupérer l'Item File afin d'avoir les informations de config, le nom, etc.
    if(props.existingImageId){
      useFetch(async () => {
        const result: ApiResponse = await $dataProvider.invoke({
          type: QUERY_TYPE.DEFAULT,
          url: 'api/files',
          id: props.existingImageId
        })

        const config = JSON.parse(result.data.config)
        coordinates.value.left = config.x
        coordinates.value.top = config.y
        coordinates.value.height = config.height
        coordinates.value.width = config.width
        image.value.name = result.data.name
        image.value.id = result.data.id
      })
    }

    //On récupère l'image...
    const { fetchState, imageLoaded } = getOne(props.existingImageId)
    const unwatch: WatchStopHandle = watch(imageLoaded, (newValue, oldValue) => {
      if (newValue === oldValue || typeof newValue === 'undefined') { return }
      image.value.src = newValue
    })

    /**
     * Quand l'utilisateur choisit une image sur sa machine
     * @param event
     */
    const loadImage = (event:any) => {
      const { files } = event.target
      if (files && files[0]) {
        reset()
        image.value.name = files[0].name
        image.value.src = URL.createObjectURL(files[0])
        image.value.file = files[0]
      }
    }

    /**
     * Losrque le cropper change de position/taille, on met à jour les coordonnées
     * @param config
     */
    const onChange = ({ coordinates: config } : any) => {
      coordinates.value = config;
    }

    /**
     * Lorsque l'on sauvegarde l'image
     */
    const save = async () => {
      fileToSave.config = JSON.stringify({
        x: coordinates.value.left,
        y: coordinates.value.top,
        height: coordinates.value.height,
        width: coordinates.value.width
      })

      //Cas d'un PUT : l'image existe déjà on bouge simplement le cropper
      if(image.value.id){
        fileToSave.id = image.value.id
        repositoryHelper.persist(File, fileToSave)
        await $dataPersister.invoke({
          type: QUERY_TYPE.MODEL,
          model: File,
          id: fileToSave.id
        })
        //On émet un évent afin de mettre à jour le formulaire de départ
        emit('reload')
      }

      //Post : on créer une nouvelle image donc on passe par l'api legacy...
      else{
        if(image.value.file){
          //On créer l'objet File à sauvegarder
          fileToSave.name = image.value.name
          fileToSave.imgFieldName = props.field
          fileToSave.visibility = 'EVERYBODY'
          fileToSave.folder = 'IMAGES'

          if(props.ownerId)
            fileToSave.ownerId = props.ownerId

          //Appel au datapersister
          const response: ApiResponse = await $dataPersister.invoke({
            type: QUERY_TYPE.FILE,
            baseUrl: $config.baseURL_Legacy,
            data: fileToSave.$toJson(),
            file: image.value.file
          })
          //On émet un évent afin de mettre à jour le formulaire de départ
          emit('update', response.data['@id'])
        }else{
          //On reset l'image : on a appuyer sur "poubelle" puis on enregistre
          emit('reset')
        }
      }
    }

    /**
     * On choisit de supprimer l'image présente
     */
    const reset = () => {
      image.value.src = null
      image.value.file = null
      image.value.name = null
      image.value.id = null
      URL.revokeObjectURL(image.value.src)
    }

    /**
     * Lorsqu'on démonte le component on supprime le watcher et on revoke l'objet URL
     */
    onUnmounted(() => {
      unwatch()
        if (image.value.src) {
          URL.revokeObjectURL(image.value.src)
        }
    })

    return {
      image,
      save,
      loadImage,
      cropper,
      reset,
      fetchState,
      coordinates,
      onChange,
      defaultSize
    }
  }
})

</script>

<style lang="scss">
  .vue-advanced-cropper__stretcher{
    height: auto !important;
    width: auto !important;
  }
  .loading{
    height: 300px;
  }
  .upload {
    user-select: none;
    padding: 20px;
    display: block;
    &__cropper {
       border: solid 1px #eee;
       min-height: 500px;
       max-height: 500px;
     }
    &__cropper-wrapper {
       position: relative;
     }
    &__reset-button {
      position: absolute;
      right: 20px;
      bottom: 20px;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
      height: 42px;
      width: 42px;
      background: rgba(#3fb37f, 0.7);
      transition: background 0.5s;
      &:hover {
        background: #3fb37f;
      }
    }
    &__buttons-wrapper {
       display: flex;
       justify-content: center;
       margin-top: 17px;
     }
    &__button {
       border: none;
       outline: solid transparent;
       color: white;
       font-size: 16px;
       padding: 10px 20px;
       background: #3fb37f;
       cursor: pointer;
       transition: background 0.5s;
       margin: 0 16px;
      &:hover,
      &:focus {
         background: #38d890;
       }
      input {
        display: none;
      }
    }
  }
</style>
