<script setup>

import { ref, useTemplateRef, nextTick, computed } from 'vue';
import Button from './Button.vue';
import Icon from './Icon.vue';

const emit = defineEmits([ 'confirm', 'reject', 'close', 'alternate' ]);

const props = defineProps({
  title: String,
  confirmStyle: String, // success, danger, ''
  rejectStyle: String, // success, danger, ''
  alternateStyle: String, // success, danger, ''
  zIndex: {
    type: Number,
    default: 2000
  },
  showX: {
    type: Boolean,
    default: false
  },
  confirmBusy: {
    type: Boolean,
    default: false
  },
  confirmActive: {
    type: Boolean,
    default: true
  },
  alternateBusy: {
    type: Boolean,
    default: false
  },
  alternateActive: {
    type: Boolean,
    default: true
  },
  rejectActive: {
    type: Boolean,
    default: true
  },
  center: {
    type: Boolean,
    default: false
  },
  dismissable: {
    type: Boolean,
    default: true
  },
  confirmLabel: String,
  rejectLabel: String,
  alternateLabel: String,
  style: '',
});

const mergedStyle = computed(() => {
  if (typeof props.style === 'object') return { 'z-index': props.zIndex+1, ...props.style };
  if (typeof props.style === 'string') return props.style = `${props.style}; zIndex: ${props.zIndex+1}`;
  return `zIndex: ${props.zIndex+1}`
})

const visible = ref(false);
const dialog = useTemplateRef('dialog');
const dialogBody = useTemplateRef('dialogBody');

async function open() {
  visible.value = true;

  // try to focus some form elements else just the dialog
  await nextTick();
  const focusElement = dialogBody.value.querySelector('input:not([disabled]):not([readonly]):not([style*="display:none"]):not([style*="display: none"])') || dialog.value;
  focusElement.focus();
}

function close() {
  // already closing
  if (!visible.value) return;

  visible.value = false;
  emit('close');
}

function onConfirm() {
  emit('confirm');
}

function onDismiss() {
  if (!props.dismissable) return;
  onReject();
}

function onReject() {
  emit('reject');
  onClose();
}

function onClose() {
  visible.value = false;
  emit('close');
}

function onAlternateAction() {
  emit('alternate');
}

defineExpose({ open, close });

</script>

<template>
  <teleport to="#app">
    <div>
      <Transition name="pankow-fade">
        <div class="pankow-dialog-backdrop" @click="onDismiss" v-show="visible" :style="{ 'z-index': zIndex }"></div>
      </Transition>
      <Transition :name="center ? 'pankow-bounce-center' : 'pankow-bounce-center-top'">
        <div ref="dialog" class="pankow-dialog" v-bind="$attrs" :class="{ 'pankow-dialog-center': center }" v-show="visible" @keydown.esc="onDismiss" tabindex="0" :style="mergedStyle">
          <div class="pankow-dialog-header" v-show="title">
            {{ title }}
          </div>
          <div class="pankow-dialog-body" ref="dialogBody" :class="{ 'pankow-dialog-body-no-header': !title, 'pankow-dialog-body-no-buttons': !(rejectLabel || confirmLabel) }">
            <slot></slot>
          </div>
          <div class="pankow-dialog-buttons" v-if="rejectLabel || confirmLabel || alternateLabel">
            <Button :[alternateStyle]="!!alternateStyle" @click="onAlternateAction" v-show="alternateLabel" :loading="alternateBusy" :disabled="alternateBusy || !alternateActive">{{ alternateLabel }}</Button>
            <div style="flex-grow: 1;"></div>
            <Button :[rejectStyle]="!!rejectStyle" @click="onReject" v-show="rejectLabel" :disabled="!rejectActive">{{ rejectLabel }}</Button>
            <Button :[confirmStyle]="!!confirmStyle" @click="onConfirm" v-show="confirmLabel" :loading="confirmBusy" :disabled="confirmBusy || !confirmActive">{{ confirmLabel }}</Button>
          </div>
          <Icon v-if="showX" class="pankow-dialog-x-close" icon="fa-solid fa-xmark" style="cursor: pointer;" @click="onReject"/>
        </div>
      </Transition>
    </div>
  </teleport>
</template>

<style>

.pankow-dialog-backdrop {
  position: fixed;
  height: 100%;
  width: 100%;
  left: 0px;
  top: 0px;
  z-index: 2001;
  background-color: var(--pankow-dialog-backdrop-color);
}

.pankow-dialog {
  position: absolute;
  background-color: var(--pankow-dialog-background-color);
  min-width: min(95%, 450px);
  max-width: calc(100% - 20px);
  max-height: calc(100% - 40px);
  box-shadow: 0 2px 5px rgba(0,0,0,.1);
  z-index: 2002;
  border-radius: var(--pankow-border-radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  outline: none;
}

.pankow-dialog-x-close {
  position: absolute;
  font-size: 14px;
  top: 10px;
  right: 10px;
}

.pankow-dialog-center {
  position: fixed;
  top: 50%;
  transform: translateX(-50%) translateY(-50%);
}

.pankow-dialog-header {
  font-size: 20px;
  padding: 15px;
  display: flex;
  justify-content: space-between;
}

.pankow-dialog-body {
  padding: 0 15px;
  overflow: auto;
  transition: all 250ms;
}

.pankow-dialog-body-no-header {
  padding: 15px;
  padding-bottom: 0;
}

.pankow-dialog-body-no-buttons {
  padding-bottom: 15px;
}

.pankow-dialog-buttons {
  display: flex;
  gap: 6px;
  padding: 15px;
  text-align: right;
}

</style>
