<template>
  <transition
      name="expand"
      @enter="enter"
      @leave="leave"
      @enter-cancel="cancel"
      @leave-cancel="cancel">
    <slot></slot>
  </transition>
</template>

<script setup>

  import TWEEN from '@tweenjs/tween.js';
  import { useGlobalTweenGroup } from "../lib/useGlobalTweenGroup";

  const props = defineProps({
    expandTime: {
      type: Number,
      default: 250
    }
  });

  let animation = null;

  function cancel () {
    if (animation) {
      animation.stop();
      animation = null;
    }
  }

  function enter(element, done) {
    const width = parseInt(getComputedStyle(element).width);
    const paddingTop = parseInt(getComputedStyle(element).paddingTop);
    const paddingBottom = parseInt(getComputedStyle(element).paddingBottom);

    element.style.width = width;
    element.style.position = 'absolute';
    element.style.visibility = 'hidden';
    element.style.height = 'auto';

    const height = parseInt(getComputedStyle(element).height);

    element.style.width = null;
    element.style.position = null;
    element.style.visibility = null;
    element.style.overflow = 'hidden';
    element.style.height = 0;

    animation = new TWEEN.Tween({height: 0, paddingTop: 0, paddingBottom: 0})
        .to({height: height, paddingTop: paddingTop, paddingBottom: paddingBottom}, props.expandTime)
        .onUpdate(obj => {
          element.style.height = obj.height + "px";
          element.style.paddingBottom = obj.paddingBottom + "px";
          element.style.paddingTop = obj.paddingTop + "px";
        })
        .onComplete(() => {
          animation = null;
          element.removeAttribute('style');
          element.style.opacity = 0.99;
          setTimeout(() => {
            // Fixes odd drawing bug in Chrome
            element.style.opacity = 1.0;
          }, 1000);
          done();
        })
        .group(useGlobalTweenGroup())
        .start();
  }

  function leave(element, done) {
    const height = parseInt(getComputedStyle(element).height);
    const paddingTop = parseInt(getComputedStyle(element).paddingTop);
    const paddingBottom = parseInt(getComputedStyle(element).paddingBottom);

    element.style.overflow = 'hidden';

    animation = new TWEEN.Tween({height: height, paddingTop: paddingTop, paddingBottom: paddingBottom})
        .to({height: 0, paddingTop: 0, paddingBottom: 0}, props.expandTime)
        .onUpdate(obj => {
          element.style.height = obj.height + "px";
          element.style.paddingBottom = obj.paddingBottom + "px";
          element.style.paddingTop = obj.paddingTop + "px";
        })
        .onComplete(() => {
          animation = null;
          element.removeAttribute('style');
          done();
        })
        .group(useGlobalTweenGroup())
        .start();
  }

</script>

<style scoped>
  * {
    will-change: height;
    transform: translateZ(0);
    backface-visibility: hidden;
    perspective: 1000px;
  }
</style>