<template>
  <teleport
    to="#jskos-vue-modal-area">
    <transition name="fade">
      <div
        v-if="shown"
        class="jskos-vue-modal"
        v-bind="$attrs">
        <!-- Actual modal -->
        <div class="jskos-vue-modal-dialog">
          <header class="jskos-vue-modal-header">
            <slot name="header">
              <h1 />
            </slot>
            <button
              type="button"
              aria-label="Close"
              @click="shown = false">
              ×
            </button>
          </header>
          <div class="jskos-vue-modal-body">
            <slot />
          </div>
          <footer>
            <slot name="footer" />
          </footer>
        </div>
        <!-- Semi-transparent backdrop -->
        <div
          class="jskos-vue-modal-backdrop"
          @click="shown = false" />
      </div>
    </transition>
  </teleport>
</template>

<script setup>
import { computed, onBeforeMount, ref } from "vue"
import "../shared.css"

defineOptions({
  inheritAttrs: false,
})

const props = defineProps({
  modelValue: {
    type: Boolean,
    required: false,
    default: undefined,
  },
})

const emit = defineEmits(["update:modelValue"])

onBeforeMount(() => {
  // Check if #jskos-vue-modal-area already exists
  const id = "jskos-vue-modal-area"
  const existing = document.getElementById(id)
  if (!existing) {
    // Create element and append to body
    const element = document.createElement("div")
    element.id = id
    document.body.appendChild(element)
  }
})

const internalShown = ref(false)
const shown = computed({
  get() {
    if (props.modelValue === undefined) {
      return internalShown.value
    }
    return props.modelValue
  },
  set(value) {
    internalShown.value = value
    emit("update:modelValue", value)
  },
})

const show = () => {
  shown.value = true
}
const hide = () => {
  shown.value = false
}

defineExpose({
  show,
  hide,
})
</script>

<style>
.jskos-vue-modal {
  position: fixed;
  top: 0;
  left: 0;
  z-index: var(--jskos-vue-modal-zIndexBase);
  width: 100%;
  height: 100%;
}
.jskos-vue-modal-dialog {
  min-height: var(--jskos-vue-modal-minHeight);
  max-height: var(--jskos-vue-modal-maxHeight);
  margin: 1em;
  min-width: var(--jskos-vue-modal-minWidth);
  max-width: var(--jskos-vue-modal-maxWidth);
  width: max-content;
  background-color: var(--jskos-vue-modal-bgColor);
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translateX(calc(-50% - 1em)) translateY(calc(-50% - 1em));
  border-radius: 0.3rem;
  z-index: var(--jskos-vue-modal-zIndexBase);
  display: flex;
  flex-direction: column;
  align-items: stretch;
}
.jskos-vue-modal-header {
  background-color: var(--jskos-vue-modal-bgColor);
  border-bottom: 1px solid var(--jskos-vue-modal-background-color);
  display: flex;
}
.jskos-vue-modal-header > h1 {
  font-size: 1.5rem;
  margin: 1rem 1rem;
  flex: 1;
}
.jskos-vue-modal-header > button {
  padding: 1rem 1rem;
  cursor: pointer;
  background-color: transparent;
  border: 0;
  font-size: 1.5rem;
  font-weight: 700;
  opacity: .5;
}
.jskos-vue-modal-header > button:hover {
  opacity: .75;
}
.jskos-vue-modal-body {
  flex: 1;
  overflow-y: auto;
  position: relative;
}
.jskos-vue-modal-dialog > footer {
  border-top: 1px solid var(--jskos-vue-border-color);
  padding: 8px;
  font-size: var(--jskos-vue-fontSize-small);
}
.jskos-vue-modal-backdrop {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: calc(var(--jskos-vue-modal-zIndexBase) - 1);
  background-color: #000;
  opacity: 0.5;
}
</style>

<style scoped>
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.15s ease;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style>
