<template>
  <XtfConfigProvider class="demo-theme-root" :theme="demoTheme">
  <scroll-view class="xtf-demo-scroll xtf-page-scroll" direction="vertical">
    <view class="xtf-demo-page xtf-page-scroll-content">
      <text class="xtf-demo-title">Infinite Scroll</text>
      <view id="infinite-down-scene" class="xtf-demo-section">
        <text class="xtf-demo-heading">01 · 底部追加</text>
        <text id="infinite-down-status" class="xtf-demo-meta">{{ down.items.length }} 项 · {{ down.requests }} 次请求</text>
        <view class="xtf-demo-list">
          <XtfInfiniteScroll id="infinite-down" :key="revision" ref="downRef" :loading="down.busy || down.hold" :finished="down.finished" :error="down.error" :disabled="down.disabled" :offset="24" @load="load(down, false)" @retry="record('down retry')">
            <view v-for="item in down.items" :id="'infinite-down-item-' + item" :key="item" class="xtf-demo-row"><text class="xtf-demo-row-text">记录 {{ item }}</text></view>
          </XtfInfiniteScroll>
        </view>
      </view>
      <view id="infinite-up-scene" class="xtf-demo-section">
        <text class="xtf-demo-heading">02 · 顶部前插</text>
        <text id="infinite-up-status" class="xtf-demo-meta">{{ up.items.length }} 项 · {{ up.requests }} 次请求</text>
        <view class="xtf-demo-list">
          <XtfInfiniteScroll id="infinite-up" :key="revision" ref="upRef" direction="up" pull-text="下拉加载历史记录" :loading="up.busy || up.hold" :finished="up.finished" :error="up.error" :disabled="up.disabled" :offset="24" @load="load(up, true)" @retry="record('up retry')">
            <view v-for="item in up.items" :id="'infinite-up-item-' + item" :key="item" class="xtf-demo-row"><text class="xtf-demo-row-text">历史 {{ item }}</text></view>
          </XtfInfiniteScroll>
        </view>
      </view>
      <view id="infinite-error-scene" class="xtf-demo-section">
        <text class="xtf-demo-heading">03 · 失败与重试</text>
        <view class="xtf-demo-actions">
          <button id="infinite-down-fail" class="xtf-demo-button" :disabled="down.busy" @click="fail(down, 'down')">底部模拟失败</button>
          <button id="infinite-up-fail" class="xtf-demo-button" :disabled="up.busy" @click="fail(up, 'up')">顶部模拟失败</button>
        </view>
      </view>
      <view id="infinite-loading-scene" class="xtf-demo-section">
        <text class="xtf-demo-heading">04 · Loading 守卫</text>
        <view class="xtf-demo-control"><text class="xtf-demo-label">底部加载中</text><switch id="infinite-down-loading" :checked="down.hold" @change="down.hold = $event.detail.value" /></view>
        <view class="xtf-demo-control"><text class="xtf-demo-label">顶部加载中</text><switch id="infinite-up-loading" :checked="up.hold" @change="up.hold = $event.detail.value" /></view>
      </view>
      <view id="infinite-guards-scene" class="xtf-demo-section">
        <text class="xtf-demo-heading">05 · Finished / Disabled</text>
        <view class="xtf-demo-control"><text class="xtf-demo-label">底部已完成</text><switch id="infinite-down-finished" :checked="down.finished" @change="down.finished = $event.detail.value" /></view>
        <view class="xtf-demo-control"><text class="xtf-demo-label">顶部已完成</text><switch id="infinite-up-finished" :checked="up.finished" @change="up.finished = $event.detail.value" /></view>
        <view class="xtf-demo-control"><text class="xtf-demo-label">禁用底部加载</text><switch id="infinite-down-disabled" :checked="down.disabled" @change="down.disabled = $event.detail.value" /></view>
        <view class="xtf-demo-control"><text class="xtf-demo-label">禁用顶部加载</text><switch id="infinite-up-disabled" :checked="up.disabled" @change="up.disabled = $event.detail.value" /></view>
      </view>
      <view id="infinite-check-scene" class="xtf-demo-section">
        <text class="xtf-demo-heading">06 · 位置检查与事件</text>
        <view class="xtf-demo-actions">
          <button id="infinite-check-down" class="xtf-demo-button" @click="check(false)">检查底部</button>
          <button id="infinite-check-up" class="xtf-demo-button" @click="check(true)">检查顶部</button>
          <button id="infinite-reset" class="xtf-demo-button" @click="reset">重置</button>
        </view>
        <view id="infinite-event-log" class="xtf-demo-log"><text v-for="entry in logs" :key="entry" class="xtf-demo-log-text">{{ entry }}</text></view>
      </view>
    </view>
  </scroll-view>
  </XtfConfigProvider>
</template>

<script setup lang="uts">
import { useDemoTheme } from '@/pages/demo-theme.uts'
import XtfConfigProvider from '@/uni_modules/xtf-linkuiunix/components/xtf-config-provider/xtf-config-provider.uvue'
const demoTheme = useDemoTheme()
import { onUnmounted, reactive, ref } from "vue"
import XtfInfiniteScroll from "@/uni_modules/xtf-linkuiunix/components/xtf-infinite-scroll/xtf-infinite-scroll.uvue"

type Scene = { items: number[]; busy: boolean; hold: boolean; finished: boolean; error: boolean; disabled: boolean; requests: number; timer: number }
function initial(): Scene {
  return { items: [101, 102, 103, 104, 105, 106, 107, 108], busy: false, hold: false, finished: false, error: false, disabled: false, requests: 0, timer: 0 }
}
const down = reactive(initial())
const up = reactive(initial())
const downRef = ref<InstanceType<typeof XtfInfiniteScroll> | null>(null)
const upRef = ref<InstanceType<typeof XtfInfiniteScroll> | null>(null)
const revision = ref(0)
const logs = ref<string[]>([])
let sequence = 0
let disposed = false

function record(message: string): void {
  sequence++
  logs.value.unshift(sequence.toString() + ' · ' + message)
  if (logs.value.length > 12) logs.value.pop()
}

function load(scene: Scene, prepend: boolean, shouldFail: boolean = false): void {
  const name = prepend ? 'up' : 'down'
  if (disposed || scene.busy || scene.hold || scene.finished || scene.disabled) {
    record(name + ' load blocked')
    return
  }
  scene.busy = true
  scene.error = false
  scene.requests++
  record(name + ' load #' + scene.requests)
  scene.timer = setTimeout(() => {
    scene.timer = 0
    if (disposed) return
    if (shouldFail) {
      scene.error = true
      scene.busy = false
      record(name + ' error')
      return
    }
    if (prepend) {
      const first = scene.items[0]
      scene.items = [first - 4, first - 3, first - 2, first - 1].concat(scene.items)
    } else {
      const last = scene.items[scene.items.length - 1]
      scene.items = scene.items.concat([last + 1, last + 2, last + 3, last + 4])
    }
    if (scene.items.length >= 24) scene.finished = true
    scene.busy = false
    record(name + (prepend ? ' prepend 4' : ' append 4'))
  }, 600)
}

function fail(scene: Scene, name: string): void {
  load(scene, name == 'up', true)
}

function check(prepend: boolean): void {
  record(prepend ? 'up check' : 'down check')
  if (prepend) upRef.value?.check()
  else downRef.value?.check()
}

function clearRequests(): void {
  if (down.timer != 0) clearTimeout(down.timer)
  if (up.timer != 0) clearTimeout(up.timer)
  down.timer = 0
  up.timer = 0
}

function reset(): void {
  clearRequests()
  Object.assign(down, initial())
  Object.assign(up, initial())
  revision.value++
  logs.value = []
  sequence = 0
  record('reset')
}
onUnmounted(() => {
  disposed = true
  clearRequests()
})
</script>

<style>
.xtf-demo-scroll { display: flex; flex-direction: column; flex: 1; width: 100%; height: 100%; }
.xtf-demo-page { display: flex; flex-direction: column; width: 100%; padding: 24rpx; background-color: var(--xtf-color-page, #f8fafc); }
.xtf-demo-title { color: var(--xtf-color-text, #0f172a); font-size: 36rpx; font-weight: 700; }
.xtf-demo-section { display: flex; flex-direction: column; width: 100%; padding-top: 24rpx; padding-bottom: 24rpx; border-bottom: 1px solid var(--xtf-color-border, #e2e8f0); }
.xtf-demo-heading { color: var(--xtf-color-text, #0f172a); font-size: 28rpx; font-weight: 600; margin-bottom: 12rpx; }
.xtf-demo-meta { color: var(--xtf-color-text-secondary, #64748b); font-size: 24rpx; margin-bottom: 12rpx; }
.xtf-demo-list { display: flex; flex-direction: column; width: 100%; height: 240px; background-color: var(--xtf-color-surface, #ffffff); }
.xtf-demo-row { display: flex; flex-direction: column; justify-content: center; height: 48px; flex-shrink: 0; padding-left: 16px; border-bottom: 1px solid var(--xtf-color-border, #e2e8f0); }
.xtf-demo-row-text { color: var(--xtf-color-text-secondary, #334155); font-size: 26rpx; }
.xtf-demo-actions { display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; }
.xtf-demo-button { margin: 4px; padding: 0 12px; font-size: 24rpx; border-radius: 4px; }
.xtf-demo-control { display: flex; flex-direction: row; align-items: center; justify-content: space-between; min-height: 48px; }
.xtf-demo-label { color: var(--xtf-color-text-secondary, #334155); font-size: 26rpx; flex: 1; }
.xtf-demo-log { display: flex; flex-direction: column; min-height: 48px; padding: 12px; background-color: var(--xtf-color-surface, #ffffff); }
.xtf-demo-log-text { color: var(--xtf-color-text-secondary, #475569); font-size: 24rpx; line-height: 22px; }
</style>
