<template>
	<view class="VirtualizationList virtualization-list" @scroll.passive="update" >
		<component
			:is="listTag"
			:class="listClass"
		>
			<template v-for="(info, i) in visibleItems" :key="info.item.$id">
				<slot
					:item="info.item"
					:index="info.index"
					:renderIndex="i"
					:itemStyle="{ marginBottom: gap + 'px' }"
					{{ info.item.text }}
				></slot>
			</template>
		</component>
	</view>
</template>

<script lang="ts">
import { defineComponent, PropType, nextTick } from "./vue"	
import { obj } from "./types"

export default defineComponent({
	props: {
		items: { type: Array as PropType<obj[]>, default: () => [] },
		enabled: { type: Boolean, default: true },
		buffer: {
		  type: Number,
		  default: 200,
		},
		minItemHeight: { type: Number, default: 20 },
		prerender: { type: Number, default: 20 },
		listTag: { type: String, default: "view" },
		listClass: { type: String },
		itemClass: { type: String, default: "vl-item" },
		gap: { type: Number, default: 0 },
		afterCalcTop2: { type: Function as PropType<(top2: number) => number> },
		isForceVisible: {
		  type: Function as PropType<(node: obj, index: number) => boolean>,
		},
	},
	data() {
	    return {
	      start: 0,
	      end: -1,
	      top: 0,
	      bottom: 0,
	      totalHeight: 0,
	      itemsHeight: <number[]>[],
	      mountedPromise: new Promise((resolve, reject) => {
	        this._mountedPromise_resolve = resolve;
	      }),
	    };
	},
	computed: {
	    visibleItems(): { item: obj; index: number }[] {
	      const r: { item: obj; index: number }[] = [];
		  console.log(this.items)
	      this.items.forEach((item: obj, index: number) => {
	        if (!this.enabled) {
	          r.push({ item, index });
	        } else if (
	          (index >= this.start && index <= this.end) ||
	          (this.isForceVisible && this.isForceVisible(item, index))
	        ) {
	          r.push({ item, index });
	        }
	      });
		  console.log(r)
	      return r;
	    },
	},
	watch: {
	    enabled: {
	      immediate: true,
	      handler() {
	        if (!this.enabled) {
	          // @ts-ignore
	          this.totalHeight = undefined;
	        }
	      },
	    },
	},
	methods: {
		getItemElHeight(el: UniApp.NodesRef) {
			return new Promise((resolve, reject) => {
				el.boundingClientRect(res => {
					if(res) {
						resolve(res)
					} else {
						reject(res)
					}
				}).exec()
			})
		},
		update() {
			const task = async () => {
				this.start = 0;
				this.end = this.items.length;
			}
		}
	},
	created() {
	    this.bottom = this.prerender - 1;
	},
	mounted() {
	    // @ts-ignore
	    this._mountedPromise_resolve!(null);
	    let updatedOnce = false;
	    this.$watch(
	      () => [this.items],
	      () => {
	        this.itemsHeight = [];
	        nextTick(() => {
	          this.update();
	          if (!updatedOnce) {
	            this.update();
	          }
	          updatedOnce = true;
	        });
	      },
	      { immediate: true }
	    );
	    this.$watch(
	      () => [this.buffer],
	      () => {
	        this.update();
	      }
	    );
	}
})
</script>

<style lang="scss">
.vl-items {
  overflow: hidden;
  box-sizing: border-box;
}
</style>