<script setup>
import Empty from "../Empty/Empty.vue";
import pages from "@/pages.json";
import { ref, onMounted, watchEffect } from "vue";
import { getRoute, router } from "../../utils/router";
import { getRect, debounce } from "../../utils";
import { getCurrentInstance } from "vue";

const props = defineProps({
  showBottom: {
    type: Boolean,
    default: false,
  },
  bottomText: {
    type: String,
    default: "~已经到底了~",
  },
  scrollX: {
    type: Boolean,
    default: false,
  },
  scrollY: {
    type: Boolean,
    default: true,
  },
  className: {
    type: String,
    default: "",
  },
  scrollIntoView: {
    type: String,
    default: "",
  },
  scrollStyle: {
    type: Object,
    default: () => ({}),
  },
  onBack: Function,
  showBack: {
    type: Boolean,
    default: true,
  },
  showTitle: {
    type: Boolean,
    default: true,
  },
  bgColor: {
    type: String,
    default: "#fff",
  },
  title: String,
  empty: {
    type: [Boolean],
    default: false,
  },
  border: {
    type: Boolean,
    default: false,
  },
  scrollTop: {
    type: Number,
    default: 0,
  },
});

const emit = defineEmits(["onSafeAreaChange", "onScroll"]);

const onBack = async () => {
  if (props.onBack) {
    const res = await props.onBack();
    if (!res) return;
    router.back();
    return;
  }
  router.back();
};

const safeArea = ref({
  footer: {},
  title: {},
});
const footerHeight = ref(0);

onMounted(() => {
  const systemInfo = uni.getWindowInfo();
  // 判断是否为tabbar页面
  safeArea.value = {
    ...systemInfo.safeArea,
    source: systemInfo.safeArea,
  };

  // 解决部分安卓手机安全顶部为0 的bug
  if (!safeArea.value.top) {
    safeArea.value.top = systemInfo.statusBarHeight || 40;
  }

  const isTarbarPage = pages.tabBar.list
    .map((item) => item.pagePath)
    .includes(getRoute().routeList[0].path);

  if (isTarbarPage) {
    // 高度再减掉tabbar高度
    safeArea.value.height -= 50;
    // 减去系统导航栏高度
    safeArea.value.height -= systemInfo.statusBarHeight - 18;
  }
  // 24是内边距
  safeArea.value.width -= 24;

  const instance = getCurrentInstance();
  // 获取头部高度
  getRect({
    name: ".title",
    onSuccess(res) {
      safeArea.value.title = res;
      safeArea.value.height -= props.showTitle
        ? safeArea.value.title?.height
        : 0;
    },
    instance,
  });
  // 获取底部高度
  getRect({
    name: ".bottom-button",
    onSuccess(res) {
      safeArea.value.footer = res;
      safeArea.value.height -= safeArea.value.footer?.height;
      safeArea.value.height += 22; // 剩余高度
    },
    instance,
  });
});

watchEffect(() => {
  emit("onSafeAreaChange", safeArea.value);
});

const onScroll = debounce((e) => {
  emit("onScroll", e);
}, 100);

defineExpose({
  safeArea: safeArea.value,
});
</script>

<template>
  <view class="container" :style="{ background: bgColor }">
    <view
      class="title"
      :style="{
        paddingTop: `${safeArea.top}px`,
        background: 'transparent',
      }"
      v-if="showTitle"
    >
      <uni-nav-bar
        :left-icon="showBack ? 'left' : ''"
        @clickLeft="onBack"
        :border="border"
        :title="title"
        fixed
        :backgroundColor="bgColor"
      />
    </view>
    <scroll-view
      enable-flex
      enable-passive
      enhanced
      paging-enabled
      show-scrollbar
      enable-back-to-top
      scroll-with-animation
      scroll-anchoring
      :scroll-x="scrollX"
      :scroll-y="scrollY"
      :scroll-top="scrollTop"
      :scroll-into-view="scrollIntoView"
      @scroll="onScroll"
      v-if="!empty"
    >
      <view
        :class="['scroll-view', scrollX ? 'topic-scroll' : '']"
        :style="{
          height: `${safeArea.height}px`,
          whiteSpace: scrollX ? 'nowrap' : 'normal',
          ...scrollStyle,
        }"
      >
        <slot></slot>
      </view>
      <!-- 底部文字 -->
      <view v-if="showBottom && bottomText" class="bottom-text">
        {{ bottomText }}
      </view>
    </scroll-view>
    <view class="empty" v-else>
      <Empty />
    </view>
    <view
      v-if="$slots.footer"
      class="bottom-button"
      :style="{
        width: `${safeArea.width}px`,
        background: 'transparent',
      }"
    >
      <slot name="footer" :footer-height="footerHeight" />
    </view>
  </view>
</template>

<style lang="scss" scoped>
@import "@/uni.scss";

.title {
  position: sticky;
  top: 0;
  z-index: 9999;
}

.empty {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
}

.container {
  display: flex;
  flex-direction: column;
  color: #333;
  box-sizing: content-box;
  position: relative;
  height: 100vh;
}

.scroll-view {
  position: relative;
  padding: 24rpx 24rpx 0;
  box-sizing: content-box;
  display: flex;
  flex-direction: column;
  gap: 24rpx;
}

.bottom-text {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
}

.bottom-button {
  width: 100%;
  padding: 24rpx;
  position: absolute;
  bottom: 0;
}

.topic-scroll {
  white-space: nowrap;
  display: inline-flex;
}
</style>
