<template>
  <transition name="slide-up" appear mode="out-in" @after-leave="resetDist">
    <div class="bottom-sheet" tabindex="0" @click="close" v-show="activeStatus">
      <div
        class="wrapper"
        :style="modalTransform"
        @click.stop
        :class="{ transition: state.modalTransition }"
      >
        <div
          v-if="draggable"
          class="header"
          :class="{ draggable }"
          ref="header"
        ></div>
        <div class="body">
          <slot></slot>
        </div>
      </div>
    </div>
  </transition>
</template>
<script lang="ts">
import {
  computed,
  defineComponent,
  onBeforeUnmount,
  onMounted,
  reactive,
  ref,
  watch,
} from "vue";
import { Scroll } from "@/utils";
export default defineComponent({
  props: {
    active: {
      default: false,
      type: Boolean,
    },
    draggable: {
      default: true,
      type: Boolean,
    },
  },
  setup({ draggable, active }, { emit }) {
    const header = ref<any>("");
    const activeStatus = ref<boolean>(false);
    const state: {
      modalTransition: boolean;
      prevPositionY: any;
      yDist: number;
    } = reactive({
      modalTransition: true,
      prevPositionY: null,
      yDist: 0,
    });

    const modalTransform = computed((): object => {
      return {
        transform: "translateY(" + (state.yDist > 0 ? state.yDist : 0) + "px)",
      };
    });

    const close = (): void => {
      activeStatus.value = false;
    };
    const resetDist = (): void => {
      emit("close");
      state.yDist = 0;
    };

    const touchStartHandler = (event: TouchEvent): void => {
      state.prevPositionY = event.touches[0].clientY;
      state.modalTransition = false;
    };

    const touchMoveHandler = (event: TouchEvent): void => {
      event.preventDefault();

      state.yDist += event.touches[0].clientY - state.prevPositionY;
      state.prevPositionY = event.touches[0].clientY;
    };

    const touchEndHandler = (): void => {
      state.prevPositionY = null;
      if (state.yDist > 150) {
        close();
      } else {
        state.modalTransition = true;
        state.yDist = 0;
      }
    };

    const setOverscroll = (value: string): void => {
      const ht: HTMLElement | null = document.querySelector("html");
      (document.body.style as any)["overscrollBehavior"] = value;

      if (ht) {
        ht.style["overscrollBehavior"] = value;
      }
    };

    onMounted((): void => {
      activeStatus.value = true;
      if (!draggable) {
        return;
      }

      header.value.addEventListener(
        "touchstart",
        touchStartHandler as EventListener
      );
      header.value.addEventListener(
        "touchmove",
        touchMoveHandler as EventListener
      );
      header.value.addEventListener(
        "touchend",
        touchEndHandler as EventListener
      );
    });
    onBeforeUnmount((): void => {
      if (!draggable) {
        return;
      }
      header.value.removeEventListener(
        "touchstart",
        touchStartHandler as EventListener
      );
      header.value.removeEventListener(
        "touchmove",
        touchMoveHandler as EventListener
      );
      header.value.removeEventListener(
        "touchend",
        touchEndHandler as EventListener
      );
    });

    watch(
      () => active,
      (newVal: boolean) => {
        activeStatus.value = true;
        // activeStatus.value = newVal;
        if (newVal) {
          Scroll.freeze();
          setOverscroll("none");
          document.body.className = "overlay";
        } else {
          Scroll.resume();
          setOverscroll("");
          document.body.className = "";
        }
      }
    );

    return {
      modalTransform,
      header,
      resetDist,
      close,
      draggable,
      state,
      activeStatus,
    };
  },
});
</script>

<style lang="scss">
.bottom-sheet {
  width: 100vw;
  height: 100vh;
  background: rgba(142, 142, 147, 0.7);
  backdrop-filter: blur(7px);
  outline: none;
  position: fixed;
  left: 0;
  bottom: 0;
  z-index: 6;

  .wrapper {
    width: 100%;
    max-height: calc(100vh - 90px);
    background-color: var(--background-primary);
    border-top-right-radius: 16px;
    border-top-left-radius: 16px;
    position: absolute;
    bottom: 0;
    left: 0;
    display: flex;
    flex-direction: column;

    &.transition {
      transition: transform 0.3s ease;
    }

    .header {
      height: 32px;
      position: relative;
      flex-shrink: 0;

      &.draggable {
        &:after {
          content: "";
          left: 50%;
          top: 8px;
          width: 68px;
          height: 2px;
          background-color: var(--grey-5);
          transform: translateX(-50%);
          position: absolute;
        }
      }
    }

    .body {
      min-height: 18vh;
      padding: 0 16px 16px;
      overflow-y: scroll;
      overflow-x: hidden;
      flex-grow: 1;
    }
  }
}

.slide-up-enter-active,
.slide-up-leave-active {
  transition: background 0.4s cubic-bezier(0.86, 0, 0.07, 1);

  .wrapper {
    transition: transform 0.3s cubic-bezier(0.79, 0.14, 0.15, 0.86);
  }
}

.slide-up-enter-from,
.slide-up-leave-to {
  background-color: rgba(0, 0, 0, 0) !important;
  pointer-events: none;

  .wrapper {
    transform: translateY(100%) !important;
  }
}
</style>
