<template>
  <ScrollView ref="scroll" class="brand-scroll" scrollbar>
    <div class="brand-content" ref="content">
      <div
        class="groups"
        v-for="(item, i) of filteredList"
        :ref="
          el => {
            groups[i] = el
          }
        "
        v-show="item.shopList.length"
        :key="item.name"
      >
        <h1 class="info">
          {{ item.name }}<span class="meta">/ {{ item.shopList.length }}个</span>
          <span v-if="item.name === currentFloor.floor" class="current" id="current">您在本层</span>
        </h1>
        <div class="group" :class="{ isRow }">
          <ShopItem
            :config="config"
            :isGuide="path === '/guide' && !isRow"
            :isRow="isRow"
            :isFood="isFood"
            :shop="el"
            @click="handleShop(el)"
            v-for="el of item.shopList"
            :isActive="shop && shop.shopCode === el.shopCode"
            :key="el.shopCode"
          />
        </div>
      </div>
    </div>
    <div class="indicator" :style="{ visibility: hasScollBar ? 'visible' : 'hidden' }" id="indicator" ref="indicatorWrapper">
      <div class="handle">{{ filteredList[indicatorIndex]?.name }}</div>
    </div>
  </ScrollView>
</template>

<script setup>
import { ref, nextTick, watch, computed } from 'vue'
import ShopItem from '@/base/ShopItem/ShopItem.vue'
import ScrollView from '@/base/ScrollView/ScrollView.vue'
import { storeToRefs } from 'pinia'
import { useStore } from '@/store/root'
import { useElementSize, useMutationObserver, useThrottleFn } from '@vueuse/core'
import { getTranslateValues } from './getTranslateValues'

const store = useStore()
const { currentFloor, path } = storeToRefs(store)
const indicatorWrapper = ref(null)
const scroll = ref(null)
const content = ref(null)
const groups = ref([])
const { height: containerHeight, width: containerWidth } = useElementSize(scroll)

const { height: contentHeight } = useElementSize(content)
const filteredList = computed(() => props.list.filter(({ shopList }) => shopList.length > 0))
const hasScollBar = computed(() => containerHeight.value < contentHeight.value)
const heights = computed(() => groups.value.map(useElementSize).map(({ height }) => height))
const bounds = computed(() =>
  heights.value.reduce((acc, nxt, i) => {
    const arr = [...acc]
    arr[i] = i === 0 ? nxt.value : arr[i - 1] + nxt.value
    return arr
  }, [])
)
const y = ref(0)

const indicatorIndex = computed(() =>
  bounds.value.findIndex((el, i) => {
    const start = 40 - y.value
    if (i === 0 && start < el) return true
    if (i === bounds.value.length - 1) return true
    return start > bounds.value[i - 1] && start <= el
  })
)
const throttledFn = useThrottleFn(([{ attributeName, target }]) => {
  if (attributeName === 'style') y.value = getTranslateValues(target).y
}, 500)

useMutationObserver(content, throttledFn, {
  attributes: true
})
const props = defineProps({
  list: Array,
  config: Object,
  isRow: Boolean,
  isFood: Boolean,
  shop: Object,
  needFocus: Boolean
})

const emits = defineEmits(['click'])
function handleShop(item) {
  emits('click', item)
}

watch(containerHeight, () =>
  nextTick(() => {
    scroll.value.refresh()
    if (props.shop) {
      const el = document.getElementById(props.shop.houseNumber)
      if (!el) return
      nextTick(() => {
        scroll.value.scrollToElement(el, 500, 0, -100)
      })
    } else {
      const el = document.getElementById('current')
      if (!el) return
      nextTick(() => {
        scroll.value.scrollToElement(el, 500, 0, -100)
      })
    }
  })
)

watch(containerWidth, () =>
  nextTick(() => {
    scroll.value.refresh()
    if (props.shop) {
      const el = document.getElementById(props.shop.houseNumber)
      if (!el) return
      nextTick(() => {
        scroll.value.scrollToElement(el, 500, 0, -100)
      })
    } else {
      const el = document.getElementById('current')
      if (!el) return
      nextTick(() => {
        scroll.value.scrollToElement(el, 500, 0, -100)
      })
    }
  })
)

watch(
  () => props.isRow,
  () =>
    nextTick(() => {
      scroll.value.refresh()
    })
)
watch(
  () => props.list,
  () =>
    nextTick(() => {
      scroll.value.refresh()
      scroll.value.scrollTo(0, 0)
      if (props.shop) {
        const el = document.getElementById(props.shop.houseNumber)
        if (!el) return
        nextTick(() => {
          scroll.value.scrollToElement(el, 500, 0, -100)
        })
      } else {
        const el = document.getElementById('current')
        if (!el) return
        nextTick(() => {
          scroll.value.scrollToElement(el, 500, 0, -100)
        })
      }
    })
)

watch([scroll, () => props.shop], () => {
  if (!props.needFocus || !scroll.value || !props.shop || !props.list) return
  const el = document.getElementById(props.shop.houseNumber)
  if (!el) return
  nextTick(() => {
    scroll.value.scrollToElement(el, 500, 0, -100)
  })
})
</script>

<style lang="scss" scoped>
.brand-scroll {
  position: relative;
  overflow: hidden;
  height: 1255px;
  margin-left: 68px;
  .indicator {
    position: absolute;
    height: 250px;
    top: 102px;
    right: 43px;
    width: 77px;
    pointer-events: none;
    .handle {
      position: absolute;
      width: 77px;
      height: 32px;
      background: center / cover no-repeat url(./handle.png);
      font-family: 'Montserrat';
      font-style: normal;
      font-weight: 700;
      font-size: 14px;
      line-height: 32px;
      color: rgba(0, 0, 0, 0.8);
      text-align: center;
      padding-right: 6px;
      display: flex;
      justify-content: center;
      align-items: center;
    }
  }
  &.guide {
    height: 770px;
  }
  :deep(.bscroll-vertical-scrollbar) {
    top: 102px !important;
    width: 48px !important;
    background: center / 6px 250px no-repeat url(@/assets/images/scrollBar.png);
    border-radius: 6px;
    opacity: 1 !important;
    height: 250px !important;
    &::after {
      position: absolute;
      content: '';
      left: 0;
      top: 120px;
      margin: auto;
      width: 48px;
      height: 61px;
      background: center / cover no-repeat url(@/assets/images/scrollHand.png);
      animation: slideNhide 3s ease-in-out forwards;
    }
    .bscroll-indicator {
      height: 95px !important;
      width: 6px !important;
      left: 0;
      right: 0;
      margin: auto;
      background: #ffffff !important;
      border-radius: 6px !important;
      border: none !important;
      margin-top: -50%;
    }
  }
}
.brand-content {
  padding-top: 40px;
  padding-bottom: 180px;
}
.info {
  font-weight: 900;
  font-size: 32px;
  line-height: 38px;
  color: var(--brand-floorNameColor);
  padding-bottom: 24px;
  display: flex;
  align-items: baseline;
  .meta {
    margin-left: 12px;
    font-weight: 500;
    font-size: 20px;
    line-height: 23px;
    color: var(--brand-floorMetaColor);
  }
  .current {
    display: flex;
    width: 96px;
    height: 27px;
    background: linear-gradient(113.71deg, #435acd 0%, #749cf3 100%);
    font-size: 16px;
    color: #ffffff;
    justify-content: center;
    align-items: center;
    border-radius: var(--global-radius, 6px);
    margin-left: 12px;
  }
}
.group {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  gap: 24px 8px;
  margin-bottom: 40px;
  padding-right: 68px;
}
.isRow {
  &.group {
    grid-template-columns: 1fr 1fr;
    gap: 8px 24px;
  }
}
@media (min-aspect-ratio: 1/1) {
  .brand-scroll {
    height: calc(100vh - 280px);
    &.brand {
      height: calc(100vh - 280px);
      &.showMap {
        margin-left: 54px;
        .group {
          grid-template-columns: 1fr 1fr;
          gap: 24px 8px;
        }
      }
    }
    &.guide {
      height: calc(100vh - 280px);
      margin-left: 54px;
      .group {
        grid-template-columns: 1fr 1fr;
        gap: 24px 8px;
        &.isRow {
          grid-template-columns: 1fr;
          gap: 8px;
        }
      }
    }
  }
  .group {
    grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
    gap: 32px 29px;
  }
}
</style>
