<template>
  <dialog
    ref="popupRef"
    :class="[
      {'--sheet': sheet},
      {'--drawer': drawer},
      {'--transparent-backdrop': transparentBackdrop},
    ]"
    class="ui-popup"
    @click="closeByBackdropClick"
    @cancel="close"
  >
    <div class="ui-popup__wrapper">
      <header class="ui-popup__header">
        <button
          v-if="back"
          :aria-label="$t('back')"
          class="ui-popup__back"
          type="button"
          @click="$emit('back')"
        >
          <UiIcon
            name="angle-left"
            size="20"
          />
        </button>
        <div
          v-if="$slots.title"
          class="ui-popup__title"
        >
          <slot name="title"/>
        </div>
        <button
          :aria-label="$t('close')"
          class="ui-popup__close"
          type="button"
          @click="close"
        >
          <UiIcon
            name="close"
            size="20"
          />
        </button>
      </header>
      <div
        v-if="$slots.fixedContent"
        class="ui-popup__subheader"
      >
        <slot name="fixedContent"/>
      </div>
      <div
        v-if="$slots.default"
        class="ui-popup__content"
      >
        <slot/>
      </div>
      <div
        v-if="$slots.footer"
        class="ui-popup__footer"
      >
        <slot name="footer"/>
      </div>
    </div>

    <transition mode="out-in">
      <UiSnackbar v-if="snackbarText && isSnackBarInPopup"/>
    </transition>
  </dialog>
</template>

<script setup lang="ts">
import { onBackdropClick } from '../../runtime';

const { scrollLock, scrollUnlock } = useGlobalScrollLock();

const { snackbarText, isSnackBarInPopup, enterPopup, leavePopup } = useSnackbar();

const { registerOverlay, releaseOverlay } = useOverlayStack();

const popupRef = ref();
const emit = defineEmits<{
  (eventName: 'update:modelValue', value: boolean): void
  (eventName: 'back'): void
  (eventName: 'close'): void
}>();

const props = defineProps<{
  modelValue: boolean
  back?: boolean
  transparentBackdrop?: boolean
  sheet?: boolean
  drawer?: boolean
  title?: string
  notModal?: boolean
}>();

onMounted(() => {
  enterPopup();
  scrollLock();
  registerOverlay(popupRef.value);
  if (props.notModal) {
    popupRef.value.show();
  } else {
    popupRef.value.showModal();
  }
  popupRef.value.focus({ preventScroll: true });
});

onBeforeUnmount(() => {
  leavePopup();
  scrollUnlock();
  releaseOverlay(popupRef.value);
});

function close() {
  emit('close');
  emit('update:modelValue', false);
}

function closeByBackdropClick(event: Event) {
  const target = event.target as HTMLDialogElement;
  onBackdropClick(target, close);
}
</script>

<style lang="scss">
.ui-popup {
  @include surface(overlay);
}

.ui-popup[open] {
  position: fixed;
  inset: 0;
  z-index: $z-index-popup;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  height: 100dvh;
  max-height: 100vh;
  max-height: 100dvh;

  @include to-br(sm) {
    width: 100vw;
  }
}

.ui-popup[open]:not(.--sheet) {
  @include to-br(sm) {
    padding: 16px;
  }
}

.ui-popup__wrapper {
  display: flex;
  flex-direction: column;
  background: $popup-content-bg;
  color: $popup-text;
  scrollbar-color: $popup-scrollbar transparent;
  scrollbar-width: thin;
  border-radius: $radius-2xl;
  border: 1px solid $popup-border;
  overflow: hidden;
  height: auto;

  @include from-br(sm) {
    $margin-block: 32px;

    margin: $margin-block auto;
    max-height: calc(100vh - $margin-block * 2);
    min-width: var(--popup-min-width, #{$popup-min-width});
  }

  @include to-br(sm) {
    width: 100%;
  }
}

.ui-popup.--sheet .ui-popup__wrapper {
  max-height: 98vh;
  max-height: 98dvh;

  @include to-br(sm) {
    width: 100vw;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
  }
}

.ui-popup:not(.--transparent-backdrop)::backdrop {
  backdrop-filter: blur($blur-sm);
  background-color: $popup-decorate-bg;
}

.ui-popup.--transparent-backdrop::backdrop {
  background-color: transparent;

  @include from-br(sm) {
    backdrop-filter: blur($blur-sm);
  }
}

.ui-popup__title {
  @include font-lg;

  display: grid;
  place-content: center;
  text-transform: uppercase;
  grid-column: 1/-1;
  grid-row: 1;
  padding-inline: 24px;
  text-align: center;
  font-weight: 700;
  letter-spacing: var(--tracking-wide);
}

.ui-popup.--without-close .ui-popup__title {
  padding-right: 0;
  place-content: normal;
}

.ui-popup__header {
  position: relative;
  display: grid;
  align-items: center;
  grid-template-columns: auto 1fr auto;
  column-gap: 8px;
  padding-block: 12px;
  padding-inline: 24px;
  border-bottom: 1px solid $popup-border;
  background-color: $popup-header-bg;

  @include from-br(sm) {
    padding-block: 14px;
  }
}

.ui-popup__back,
.ui-popup__close {
  position: relative;
  grid-row: 1;
  display: grid;
  place-content: center;
  color: $popup-close-icon;

  @include hover(color) {
    color: $popup-close-icon--hover;
  }

  &::after {
    @include area-point;
  }
}

.ui-popup__close {
  display: grid;
  place-content: center;
  grid-column: 3;
}

.ui-popup__back {
  grid-column: 1;
}

.ui-popup__content {
  flex: 1;
  max-height: calc(100dvh - 80px);
  overflow: auto;
  background-color: $popup-content-bg;
  padding: 24px;

  @include from-br(sm) {
    padding: 16px;
  }
}

.ui-popup[open].--sheet .ui-popup__content {
  @include to-br(sm) {
    padding: 0;
  }
}

.ui-popup[open].--sheet {
  display: grid;
  place-content: end;
  border-radius: 16px 16px 0 0;
  height: auto;

  @include from-br(sm) {
    place-content: center;
    border-radius: 0;
  }
}

.ui-popup[open].--sheet .ui-popup__wrapper {
  border-radius: 16px 16px 0 0;

  @include from-br(sm) {
    border-radius: 16px;
  }
}

.ui-popup__subheader {
  padding: 16px;
  border-bottom: 1px solid $popup-border;

  @include from-br(sm) {
    padding: 24px;
  }
}

.ui-popup__footer {
  padding: 16px 20px;
  border-top: 1px solid $popup-footer-border;
}

.ui-popup[open].--drawer {
  justify-content: flex-start;
  align-items: stretch;
  padding: 0;
  width: 100vw;
  max-width: 100vw;
}

.ui-popup.--drawer .ui-popup__wrapper {
  width: 100vw;
  height: 100dvh;
  max-height: 100dvh;
  margin: 0;
  border-radius: 0;
  border: none;

  @include from-br(sm) {
    max-width: 420px;
    min-width: 420px;
  }
}

.ui-popup.--drawer .ui-popup__content {
  max-height: unset;
  padding: 16px 20px;
}

.ui-popup.--drawer .ui-popup__title {
  @include font-base;

  text-align: start;
  place-content: start;
  padding-left: 0;
}

.ui-popup.--drawer .ui-popup__header {
  padding: 20px;
}

/* Появление анимируется только у первого оверлея в стеке, закрытие — только у последнего
   (см. useOverlayStack): иначе на переходе попап→попап диалоги едут навстречу друг другу. */
.ui-popup.--drawer:where(:not(.--no-enter-anim)) {
  &.v-enter-active {
    transition: transform 300ms ease;
  }

  &.v-enter-active::backdrop {
    transition: opacity 300ms ease;
  }

  &.v-enter-from {
    transform: translateX(-100%);
  }

  &.v-enter-from::backdrop {
    opacity: 0;
  }

  &.v-enter-to {
    transform: translateX(0);
  }
}

.ui-popup.--drawer:where(:not(.--no-leave-anim)) {
  &.v-leave-active {
    transition: transform 300ms ease;
  }

  &.v-leave-active::backdrop {
    transition: opacity 300ms ease;
  }

  &.v-leave-from {
    transform: translateX(0);
  }

  &.v-leave-to {
    transform: translateX(-100%);
  }

  &.v-leave-to::backdrop {
    opacity: 0;
  }
}

.ui-popup.--sheet:where(:not(.--no-enter-anim)) {
  @include to-br(sm) {
    &.v-enter-active {
      transition: transform 300ms ease;
    }

    &.v-enter-from {
      transform: translateY(100%);
    }

    &.v-enter-to {
      transform: translateY(0);
    }
  }
}

.ui-popup.--sheet:where(:not(.--no-leave-anim)) {
  @include to-br(sm) {
    &.v-leave-active {
      transition: transform 300ms ease;
    }

    &.v-leave-from {
      transform: translateY(0);
    }

    &.v-leave-to {
      transform: translateY(100%);
    }
  }
}
</style>
