<script setup>

import { nextTick, ref, useTemplateRef } from 'vue';

const container = useTemplateRef('container');

function getViewport() {
  var win = window,
    d = document,
    e = d.documentElement,
    g = d.getElementsByTagName('body')[0],
    w = win.innerWidth || e.clientWidth || g.clientWidth,
    h = win.innerHeight || e.clientHeight || g.clientHeight;

  return {
    width: w,
    height: h
  };
}

function getHiddenElementOuterHeight(element) {
  if (element) {
    element.style.visibility = 'hidden';
    element.style.display = 'block';
    var elementHeight = element.offsetHeight;
    element.style.display = 'none';
    element.style.visibility = 'visible';
    return elementHeight;
  }
  return 0;
}

function getHiddenElementOuterWidth(element) {
  if (element) {
    element.style.visibility = 'hidden';
    element.style.display = 'block';
    var elementWidth = element.offsetWidth;
    element.style.display = 'none';
    element.style.visibility = 'visible';
    return elementWidth;
  }
  return 0;
}

function getActiveElement(children) {
  for (const child of children) {
    if (child === document.activeElement) return child;
  }
  return null;
}

const emits = defineEmits(['close']);
const props = defineProps({
    width: {
      type: String,
      default: '',
    },
    height: {
      type: String,
      default: '',
    }
});

const openEventTimeStamp = ref(0);
const forElement = ref(null);
const isOpen = ref(false);
const pageX = ref(0);
const pageY = ref(0);
const offsetY = ref(0);
const offsetX = ref(0);
const rollUp = ref(false);

function close() {
  isOpen.value = false;
  emits('close');
}

function onBackdrop(event) {
  close();
  event.preventDefault();
}

function position() {
  let width = container.value.offsetParent ? container.value.offsetWidth : getHiddenElementOuterWidth(container.value);
  let height = container.value.offsetParent ? container.value.offsetHeight : getHiddenElementOuterHeight(container.value);
  let left = pageX.value + offsetX.value/2 - width/2;
  let top = pageY.value + 6;
  let viewport = getViewport();

  //flip
  if (left + width - document.body.scrollLeft > viewport.width) {
    // if this is like a dropdown right align instead of flip
    if (forElement.value) {
      left = forElement.value.getBoundingClientRect().left + (forElement.value.getBoundingClientRect().width - width);
    } else {
      left -= width;
    }
  }

  //flip
  if (top + height - document.body.scrollTop > viewport.height) {
    top -= height + offsetY.value + 12;
    rollUp.value = true;
  } else {
    rollUp.value = false;
  }

  //fit
  if (left < document.body.scrollLeft) {
    left = document.body.scrollLeft;
  }

  //fit
  if (top < document.body.scrollTop) {
    top = document.body.scrollTop;
  }

  container.value.style.left = left + 'px';
  container.value.style.top = top + 'px';
}

defineExpose({
  async open(event, forElem = null) {
    isOpen.value = true;
    pageX.value = forElem ? forElem.getBoundingClientRect().left : event.pageX;
    pageY.value = forElem ? forElem.getBoundingClientRect().bottom : event.pageY;
    offsetX.value = forElem ? (forElem.getBoundingClientRect().width + 2) : 0;
    offsetY.value = forElem ? (forElem.getBoundingClientRect().height + 2) : 0; // offset in case we roll up
    forElement.value = forElem;

    if (forElem) container.value.style.minWidth = forElem.getBoundingClientRect().width + 'px';

    position();
    openEventTimeStamp.value = event.timeStamp;

    event.preventDefault();
  },
  close,
});

</script>

<template>
  <teleport to="#app">
    <div class="pankow-popover-backdrop" @click="onBackdrop($event)" @contextmenu="onBackdrop($event)" v-show="isOpen"></div>
    <Transition :name="rollUp ? 'pankow-animation-pop-up' : 'pankow-animation-pop-down'">
      <div v-show="isOpen" class="pankow-popover" ref="container" :style="{ 'max-width': width || null, 'max-height': height || null }">
        <slot></slot>
      </div>
    </Transition>
  </teleport>
</template>

<style>

.pankow-popover-backdrop {
  position: fixed;
  height: 100%;
  width: 100%;
  left: 0px;
  top: 0px;
  z-index: 3001;
  background-color: transparent;
}

.pankow-popover {
  position: fixed;
  box-shadow: var(--pankow-menu-shadow);
  border-radius: var(--pankow-border-radius);
  background-color: var(--pankow-input-background-color);
  z-index: 3001;
  color: var(--pankow-color-dark);
  overflow: auto;
  outline: none;
  max-width: min(100%, 800px);
}

@media (prefers-color-scheme: dark) {
  .pankow-popover {
    color: var(--pankow-color-light-dark);
  }
}

</style>
