<template>
	<view class='index-list'>
		<view class='index-list__head'>
			<input v-model="citySearch" :placeholder='placeholder' class="index-list__input"
				placeholder-class="index-list__input__placeholder" />
		</view>
		<div>
			<div class='index-list__scroller'>
				<div ref="bigDataTablePanel" class="index-list__big-data__table-panel">
					<div ref="bigDataTableBody" class="index-list__big-data__table-body">
						<div ref="bigDataTableDataPanel" id="bigDataTableDataPanel"
							class="index-list__big-data__table-data-panel" @touchstart="bigDataTouchStartEvent"
							@touchmove.stop.prevent="bigDataScrollEvent" @touchend="bigDataTouchEndEvent"
							@mousewheel="bigDataScrollEvent">
							<div ref="bigDataTableDataMarginSpace" :style="{'margin-top':newMarginTop+'px'}"></div>
							<div v-for='item in bigDataFilteredFlatWithLineInfoCurrent' :key='item.id'>
								<div v-if='item.__line_info__.isEmptySpace'
									class="index-list__group-cell index-list__group-cell--empty-space"></div>
								<div v-else-if='!item.__line_info__.isEmptySpace&&item.__line_info__.isHead'
									class="index-list__group-head">{{item.username}}</div>
								<div v-else-if='!item.__line_info__.isEmptySpace&&!item.__line_info__.isHead'
									class="index-list__group-cell" @click="()=>{ itemClickHandler(item)}" :key="item.id"
									style="display: flex;" @longpress="()=>{itemLongPress(item)}">
									<view>
										<image src="../../static/images/tx.png"
											style="width:50rpx;height: 50rpx;margin-top: 10rpx;"></image>
									</view>
									<span
										style="padding-left: 20rpx;font-size:34rpx ;letter-spacing: 1rpx;">{{item.username}}</span>
									<span
										style="padding-left: 20rpx;font-size:34rpx ;letter-spacing: 1rpx;">({{item.phone}})</span>
								</div>

							</div>
							<div v-for='groupKey in Object.keys(bigDataFiltered)' style='' :key='groupKey'>
								<div class="index-list__group-head"
									:id='"list-archor-"+ encodeURIComponent(groupKey).replace("%","_")'>
									{{groupKey}}
								</div>
								<div class="index-list__group-cell" v-for='city in dataFiltered[groupKey]'
									@click="()=>{itemClickHandler(city)}" :clickable='true' :key="city.id">
									{{city.username}}
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>

		<view v-if='useIndex&&dataFiltered&&Object.keys(dataFiltered).length>0' class='index-list__index'
			@touchmove="indexTouchMoveHandler" @touchstart="indexTouchMoveHandler" @touchend="isZoomActiveIndex=false">
			<div class='index-list__index__wrapper'>
				<div v-for='groupKey in Object.keys(dataFiltered)' :key='groupKey' class='index-list__index__letter'
					:class='{"index-list__index__letter--active":currentActiveIndex===groupKey&&isZoomActiveIndex,
					"index-list__index__letter--active2":currentActiveIndex===groupKey}'>
					{{groupKey}}
				</div>
			</div>
		</view>
	</view>
</template>

<script>
	import {
		pinyin
	} from "@/api/convertPinyin.js";
	export default {
		name: "missthee-indexlist",
		props: {
			data: {
				type: Object,
				default: function() {
					return {}
				}
			},
			placeholder: {
				type: String,
				default: function() {
					return '输入关键字查询'
				}
			},
			useIndex: {
				type: Boolean,
				default: function() {
					return true
				}
			},
		},
		data() {
			return {
				dataFiltered: {},
				currentActiveIndex: '',
				isZoomActiveIndex: false,
				citySearch: '',
				citySeatchDebounce: null,
				bigDataFilteredLineHeightTotal: 0,
				bigDataFiltered: {},
				bigDataFilteredFlatWithLineInfo: [],
				bigDataFilteredFlatWithLineInfoCurrent: [],
				bigDataTableDataPanelEl: null,
				bigDataParam: {
					scrollHeight: 0,
					dataHeadHeight: 35, // 索引行高
					dataRowHeight: 45, // 数据行高
				},
				bigDataComputedParam: {
					dataRowTopMax: 0, //数据行滑到底，移动的最大距离
					dataRowTop: 0, //数据行当前移动的距离
				},

				bigDataScrollActionParam: {
					speed: 0,
					speedMax: 50,
					resistance: 0.5,
					prePositionY: null,
					preTimestamp: null,
					isMouseDown: false,
					timeoutObj: null
				},
				newMarginTop: 0,
				islongPress: false, //长按记录变量
			}
		},
		watch: {
			data: {
				immediate: true,
				handler() {
					this.buildDataFiltered()
				}
			},
			citySearch() {
				if (this.citySeatchDebounce) {
					clearTimeout(this.citySeatchDebounce)
					this.citySeatchDebounce = null
				}
				this.citySeatchDebounce = setTimeout(() => {
					this.buildDataFiltered()
				}, 200)
			},
			dataFiltered: {
				deep: true,
				handler() {
					this.bigDataComputedParam.dataRowTop = 0
					this.bigDataBuildData()
					this.bigDataUpdateRows()
				}
			}
		},
		mounted() {
			this.bigDataTableDataPanelEl = this.$refs.bigDataTableDataPanel
			// #ifdef H5
			this.bigDataParam.scrollHeight = this.bigDataTableDataPanelEl.offsetHeight
			// #endif
			// #ifdef APP-VUE || APP
			let view = uni.createSelectorQuery().in(this).select("#bigDataTableDataPanel")
			view.fields({
				size: true
			}, res => {
				this.bigDataParam.scrollHeight = res.height - 100
				this.afterHeight = true;
			}).exec()
			// #endif
			this.bigDataAddEvent()
			this.bigDataBuildData()
			this.bigDataUpdateRows()
			this.bigDataScrollAminate()
		},
		beforeDestroy() {
			this.bigDataClearScrollAnimate()
			this.bigDataRemoveEvent()
		},
		methods: {
			indexTouchMoveHandler(e) {
				this.isZoomActiveIndex = true
				const touch = e.touches[0];
				const target = e.currentTarget || e.target
				let currentIndex = Math.floor((touch.clientY + Object.keys(this.dataFiltered).length * 15 / 2 -
					target.offsetTop) / 15)
				currentIndex = Math.min(Object.keys(this.dataFiltered).length - 1, currentIndex)
				currentIndex = Math.max(0, currentIndex)
				if (Object.keys(this.dataFiltered)[currentIndex] !== this.currentActiveIndex) {
					this.currentActiveIndex = Object.keys(this.dataFiltered)[currentIndex]
					let currentStartLine = this.bigDataFilteredFlatWithLineInfo.find(item => item.id === 'Head:' + this
						.currentActiveIndex)
					this.bigDataComputedParam.dataRowTop = currentStartLine.__line_info__.totalHeight -
						currentStartLine
						.__line_info__.currentHeight
					this.bigDataUpdateRows()
				}
				if ("undefined" !== typeof event) {
					event.preventDefault()
					event.stopPropagation()
				}
			},
			itemClickHandler(item) {
				if (this.islongPress) {
					return
				}
				let result = {
					...item
				}
				for (let key of Object.keys(result)) {
					if (key === '__line_info__') {
						delete result[key]
					}
				}

				this.$emit('select-item', result)
			},
			itemLongPress(item) {
				this.islongPress = true
				let result = {
					...item
				}
				for (let key of Object.keys(result)) {
					if (key === '__line_info__') {
						delete result[key]
					}
				}

				let _this = this
				uni.setClipboardData({
					data: result.phone,
					success: function() {
						uni.showToast({
							title: '复制成功',
							icon: 'success'
						});
						setTimeout(() => {
							_this.islongPress = false
						}, 2000)
					}
				});
			},
			buildDataFiltered() {
				if (!this.data) {
					return {}
				}
				const resultObj = {}
				for (const groupkey of Object.keys(this.data)) {
					const cityListResult = this.data[groupkey].filter(item =>
						item.username.toLowerCase().indexOf(this
							.citySearch.toLowerCase()) >= 0
					)
					if (cityListResult && cityListResult.length > 0) {
						resultObj[groupkey] = cityListResult
					}
				}
				this.dataFiltered = resultObj
			},
			bigDataAddEvent() {
				// #ifdef APP-VUE || APP
				// plus.globalEvent.addEventListener('mousewheel', this.bigDataScrollEvent);
				// plus.globalEvent.addEventListener('touchmove', this.bigDataScrollEvent);
				// plus.globalEvent.addEventListener('touchstart', this.bigDataTouchStartEvent);
				// plus.globalEvent.addEventListener('touchend', this.bigDataTouchEndEvent);
				// #endif
				// #ifdef H5
				this.bigDataTableDataPanelEl.addEventListener('mousewheel', this.bigDataScrollEvent);
				this.bigDataTableDataPanelEl.addEventListener('touchmove', this.bigDataScrollEvent);
				this.bigDataTableDataPanelEl.addEventListener('touchstart', this.bigDataTouchStartEvent);
				this.bigDataTableDataPanelEl.addEventListener('touchend', this.bigDataTouchEndEvent);
				// #endif

			},
			bigDataRemoveEvent() {
				this.bigDataTableDataPanelEl.removeEventListener('mousewheel', this.bigDataScrollEvent);
				this.bigDataTableDataPanelEl.removeEventListener('touchmove', this.bigDataScrollEvent);
				this.bigDataTableDataPanelEl.removeEventListener('touchstart', this.bigDataTouchStartEvent);
				this.bigDataTableDataPanelEl.removeEventListener('touchend', this.bigDataTouchEndEvent);
			},
			bigDataTouchStartEvent(e) {
				this.bigDataScrollActionParam.isMouseDown = true
				this.bigDataScrollActionParam.speed = 0
			},
			bigDataTouchEndEvent(e) {
				this.bigDataScrollActionParam.isMouseDown = false
				this.bigDataScrollActionParam.prePositionY = null
			},
			bigDataScrollEvent(e) {
				let scrollEvent = e;
				// if (scrollEvent instanceof WheelEvent) {
				// #ifdef H5
				this.bigDataComputedParam.dataRowTop += (scrollEvent.wheelDelta < 0 ? 1 : -1) * 30;
				if (this.bigDataComputedParam.dataRowTop <= 0) {
					this.bigDataComputedParam.dataRowTop = 0; //滑块最多滑到顶部
				} else if (this.bigDataComputedParam.dataRowTop >= this.bigDataComputedParam.dataRowTopMax) {
					this.bigDataComputedParam.dataRowTop = this.bigDataComputedParam.dataRowTopMax; //滑块最多滑到最底部
				} else {
					e.preventDefault(); //禁用滑轮滚动默认事件。当表格滑动到边缘时再启用默认滚动事件
				}
				// #endif
				// } else 
				// if (scrollEvent instanceof TouchEvent) {
				// #ifdef APP||APP-VUE
				if (this.bigDataScrollActionParam.isMouseDown) {
					let positionY = scrollEvent.changedTouches[0].clientY
					let timeStamp = scrollEvent.timeStamp
					let step = 0
					this.bigDataScrollActionParam.prePositionY = this.bigDataScrollActionParam.prePositionY ||
						positionY
					this.bigDataScrollActionParam.preTimeStamp = this.bigDataScrollActionParam.preTimeStamp ||
						timeStamp
					let timeDuration = timeStamp - this.bigDataScrollActionParam.preTimeStamp;
					let velocity;
					if (timeDuration === 0) {
						velocity = 0
					} else {
						velocity = (positionY - this.bigDataScrollActionParam.prePositionY) / timeDuration
					}
					if (this.bigDataScrollActionParam.prePositionY !== null) {
						step = positionY - this.bigDataScrollActionParam.prePositionY
						this.bigDataComputedParam.dataRowTop -= step
					}
					this.bigDataScrollActionParam.prePositionY = positionY
					this.bigDataScrollActionParam.preTimeStamp = timeStamp
					this.bigDataScrollActionParam.speed = velocity * 16
					e.preventDefault()
					e.stopPropagation()
				}
				// #endif
				// }
				this.bigDataUpdateRows();
			},
			bigDataBuildData() {
				this.bigDataFilteredFlatWithLineInfo = []
				this.bigDataFilteredLineHeightTotal = 0
				for (let key of Object.keys(this.dataFiltered)) {
					if (this.dataFiltered[key] && this.dataFiltered[key].length > 0) {
						this.bigDataFilteredLineHeightTotal += this.bigDataParam.dataHeadHeight
						this.bigDataFilteredFlatWithLineInfo.push({
							id: "Head:" + key,
							username: key,
							__line_info__: {
								isEmptySpace: false,
								isHead: true,
								currentHeight: this.bigDataParam.dataHeadHeight,
								totalHeight: this.bigDataFilteredLineHeightTotal
							}
						})
						this.dataFiltered[key].forEach((item) => {
							this.bigDataFilteredLineHeightTotal += this.bigDataParam.dataRowHeight
							this.bigDataFilteredFlatWithLineInfo.push({
								id: "Row:" + item.id,
								username: item.username,
								phone: item.phone,
								__line_info__: {
									isEmptySpace: false,
									isHead: false,
									currentHeight: this.bigDataParam.dataRowHeight,
									totalHeight: this.bigDataFilteredLineHeightTotal
								}
							})
						})
					}
				}
				this.bigDataFilteredLineHeightTotal += this.bigDataParam.dataRowHeight
				this.bigDataFilteredFlatWithLineInfo.push({
					id: "EmptyFooter",
					username: '',
					__line_info__: {
						isEmptySpace: true,
						isHead: false,
						currentHeight: this.bigDataParam.dataRowHeight,
						totalHeight: this.bigDataFilteredLineHeightTotal
					}
				})
				//计算出数据区域滑动到最后一条数据，所需要的位移距离
				this.bigDataComputedParam.dataRowTopMax = Math.max(this.bigDataFilteredLineHeightTotal - this.bigDataParam
					.scrollHeight, 0)
			},
			bigDataUpdateRows() {
				this.bigDataComputedParam.dataRowTop = Math.max(0, this.bigDataComputedParam.dataRowTop)
				this.bigDataComputedParam.dataRowTop = Math.min(this.bigDataComputedParam.dataRowTop, this
					.bigDataComputedParam.dataRowTopMax)
				if (this.bigDataFilteredFlatWithLineInfo.length > 0) {
					//更新数据区的数据，根据滚动的距离，确定可见的第一条数据下标（此方法保证可见数据行内容的更新。注释掉此方法，拖动滚动条，数据会在开始部分一直循环）
					//遍历数据，插入窗口中可见的数据行
					let startIndex = null
					let endIndex = null

					for (let i = parseInt(this.bigDataComputedParam.dataRowTop / Math.max(this.bigDataParam.dataRowHeight,
							this.bigDataParam.dataHeadHeight), 10) - 1; i < this.bigDataFilteredFlatWithLineInfo
						.length; i++) {
						if (i < 0) {
							continue
						}
						const totalHeight = this.bigDataFilteredFlatWithLineInfo[i].__line_info__.totalHeight
						if (totalHeight >= this.bigDataComputedParam.dataRowTop && startIndex === null) {
							startIndex = i
						}
						if (totalHeight >= (this.bigDataComputedParam.dataRowTop + this.bigDataParam.scrollHeight) &&
							endIndex === null) {
							endIndex = Math.min(i + 3, this.bigDataFilteredFlatWithLineInfo.length)
						} else if (endIndex === null && this.bigDataFilteredFlatWithLineInfo.length < 10) {
							endIndex = this.bigDataFilteredFlatWithLineInfo.length
						}
						if (startIndex !== null && endIndex !== null) {
							break
						}
					}
					startIndex = startIndex || 0
					endIndex = endIndex || 0
					this.bigDataFilteredFlatWithLineInfoCurrent = this.bigDataFilteredFlatWithLineInfo.slice(startIndex,
						endIndex)
					if (this.bigDataFilteredFlatWithLineInfoCurrent && this.bigDataFilteredFlatWithLineInfoCurrent[0]) {
						const tmp = this.bigDataFilteredFlatWithLineInfoCurrent[0]
						let firstRowHeight = tmp.__line_info__.currentHeight || 0
						let firstRowTotalHeight = tmp.__line_info__.totalHeight || 0
						//数据区实现拖动滑条的位移效果（保证数据行的滚动效果，注释此方法，拖动滚动条，数据无滚动效果，但内容会更新）
						this.newMarginTop = firstRowTotalHeight - this.bigDataComputedParam.dataRowTop - firstRowHeight
						if (!this.isZoomActiveIndex) {
							this.currentActiveIndex = pinyin.getFullChars(tmp.username).charAt(0).toUpperCase();
						}
					}

				}
			},
			bigDataScrollAminate() {
				this.bigDataScrollActionParam.timeoutObj = setInterval(() => {
					if (Math.abs(this.bigDataScrollActionParam.speed) > 0 && !this.bigDataScrollActionParam
						.isMouseDown) {
						this.bigDataScrollActionParam.speed = (this.bigDataScrollActionParam.speed >= 0 ? 1 : -1) *
							Math.min(this.bigDataScrollActionParam.speedMax, Math.max(0, Math.abs(this
									.bigDataScrollActionParam.speed) - this.bigDataScrollActionParam
								.resistance))
						this.bigDataComputedParam.dataRowTop -= this.bigDataScrollActionParam.speed
						this.bigDataUpdateRows()
					}
				}, 16)
			},
			bigDataClearScrollAnimate() {
				if (this.bigDataScrollActionParam.timeoutObj) {
					clearInterval(this.bigDataScrollActionParam.timeoutObj)
					this.bigDataScrollActionParam.timeoutObj = null
				}
			}
		}
	}
</script>

<style lang='scss' scoped>
	* {
		font-family: Consolas, sans-serif;
		box-sizing: border-box !important;
		margin: 0;
		padding: 0;
	}


	.index-list__index__letter--active2 {
		color: red;
	}

	.index-list__index__letter {
		margin: 5px 0;
		font-size: 20px;
	}

	.index-list {
		position: absolute;
		top: 0;
		bottom: 0;
		width: 100%;

		&__head {
			position: absolute;
			top: 0;
			width: 100%;
			height: 50px;
			overflow: hidden;
			background-color: $uni-bg-color;
			border-bottom: 1px solid $uni-bg-color-grey;
		}

		&__input {
			box-sizing: border-box;
			width: 90%;
			height: 30px;
			padding: 0 20px;
			margin: auto;
			height: 30px;
			margin: 10px auto;
			line-height: 30px;
			background-color: $uni-bg-color-grey;
			border-radius: 30px;
			font-size: 12px;
			color: $uni-text-color;

			&__placeholder {
				text-align: center;
				color: $uni-text-color-placeholder;
			}
		}

		&__scroller {
			position: absolute;
			top: 50px;
			bottom: 0;
			width: 100%;
			background-color: white;
			overflow-x: hidden;
			overflow-y: auto;
		}

		&__big-data {

			&__table-panel {
				height: 100%;
				width: 100%;
			}

			&__table-body {
				/*因为数据区与滚动条要使用position:absolute做成左右固定布局，table-body作为其两节点的父节点，使用position: relative*/
				position: relative;
				height: 100%;
				overflow: hidden;
				background-color: white;
			}

			&__table-data-panel {
				overflow: hidden;
				position: absolute;
				left: 0;
				/*right值宽度等于滚动条的宽度。也可不设置，但滚动条会覆盖表格的最右侧*/
				/*right: 15px;*/
				width: 100%;
				height: 100%;
			}
		}

		&__group-head {
			box-sizing: border-box;
			background-color: $uni-bg-color-grey;
			color: $uni-text-color-grey;
			height: 35px;
			line-height: 45px;
			padding: 0 0 0 15px;
		}

		&__group-cell {
			box-sizing: border-box;
			background-color: $uni-bg-color;
			color: $uni-text-color;
			font-size: 14px;
			font-family: SourceHanSansSC-Regular, SourceHanSansSC;
			height: 45px;
			line-height: 45px;
			padding: 0 0 0 15px;

			&:after {
				display: block;
				position: absolute;
				content: '';
				width: 100%;
				height: 1px;
				background-color: $uni-bg-color-grey;
			}

			&:active {
				background-color: $uni-bg-color-hover;
			}

			&--empty-space {
				&:active {
					background-color: white;
				}
			}

		}

		&__index {
			position: absolute;
			right: 0;
			top: 50%;
			transform: translateY(-50%);

			&__wrapper {
				width: 20px;
				margin: 0 7px 0 0;
				text-align: center;
				background-color: rgba(0, 0, 0, 0.03);
				border-radius: 10px;
				color: $uni-text-color-grey;
				padding: 10px 0;
				font-family: Consolas, sans-serif;
			}

			&__letter {
				display: block;
				height: 15px !important;
				line-height: 15px !important;
				transition: transform 0.1s;

				&--active {
					transition: none;
					font-weight: bold;
					font-size: 50px;
					transform: translateX(-70px);
				}
			}
		}
	}
</style>