<template>
	<view class="_select">
		<view class="_mask" @touchmove.stop.prevent="() => { }" v-if="popclass" @tap="hidepop"></view>
		<view class="_pop" :animation="anidatapop" v-if="popclass" :class="popclass">
			<view class="ciy-hr"></view>
			<view class="_search" v-if="mrange.length > minselectsearch">
				<view class="itm">
					<input v-model="searchval" :placeholder="lang('placeholder.key')" @confirm="searchconfirm" />
				</view>
			</view>
			<scroll-view id="select_list" class="_list" :scroll-top="itemtop" scroll-y>
				<slot name="list" :data="{range:mrange,searchkey:searchval,popclass:popclass,onselect:Selitem}">
					<view :class="rows==1?'_flex':'_grid'" :style="'grid-template-columns: repeat('+rows+', 1fr);text-align:' + itemalign">
						<view :id="'selectitem-' + index" class="_item" :class="{_select:tvalue.id==item.id}" v-for="(item,index) in mrange" :key="index" @tap="Selitem(index)">
							{{item.name}}
						</view>
					</view>
					<template v-if="mrange.length == 0">
						<view v-if="searchval" class="_nodata">
							{{lang('select.nosearch')}}
							<text class="_code">{{searchval}}</text>
						</view>
						<view v-else class="_nodata">{{lang('select.nodata')}}</view>
					</template>
				</slot>
			</scroll-view>
			<view class="ciy-hr"></view>
			<view style="flex:1;pointer-events: none;width:100%;" @touchmove.stop.prevent="() => { }" @tap="hidepop"></view>
		</view>
		<view class="_show" :class="{_left:left}" @tap="showpop">
			<view class="_txt" :style="ciystyle">
				<view v-if="tvalue.name" :style="{color:disabled?'var(--bg6)':'var(--txt9)'}">{{tvalue.name}}</view>
				<view v-else-if="placeholder !== ''" style="color:var(--txt1);">{{placeholder?placeholder:lang('placeholder.select')}}</view>
			</view>
			<view v-if="!noarrow" class="_arrow ciy-icon-arrow" :class="{_sel:popclass}"></view>
		</view>

		<input type="hidden" :name="name" :value="tvalue.id" style="display:none;" />
		<input v-if="hasmore" type="hidden" :name="name+'_name'" :value="tvalue.name" style="display:none;" />
	</view>
</template>
<script>
	export default {
		behaviors: ['uni://form-field-group'],
		emits: ['change', 'update:modelValue', 'search'],
		props: {
			name: {
				type: String
			},
			modelValue: {
				type: [String, Number],
				default: ''
			},
			value: {
				type: [String, Number],
				default: ''
			},
			disabled: {
				type: Boolean,
				default: false
			},
			initevent: {
				type: Boolean,
				default: false
			},
			ciystyle: {
				type: [String, Object]
			},
			left: {
				type: Boolean,
				default: false
			},
			hasmore: {
				type: Boolean,
				default: false
			},
			chkuse: {
				type: Boolean,
				default: false
			},
			range: {
				type: [String, Array],
				default: []
			},
			placeholder: {
				type: String
			},
			diastema: { //上下间隙
				type: Number,
				default: 16
			},
			itemalign: { //item对齐
				type: String,
				default: ''
			},
			all: { //0值选项
				type: String,
				default: ''
			},
			noarrow: {
				type: Boolean,
				default: false
			},
			rows: {
				type: Number,
				default: 1
			},
			minselectsearch: { //选项少于n，则不显示搜索
				type: Number,
				default: 5
			}
		},
		data() {
			return {
				v: '',
				searchval: '', //搜索键入内容
				popclass: '', //值包含[btm/top]，制定弹出在上方还是下方
				anidatapop: {}, //弹出的选项动画
				itemtop: 0,
			};
		},
		watch: {
			searchval: {
				handler(newD, oldD) {
					this.$emit('search', {
						name: this.name,
						from: 'input',
						com: this,
						value: newD
					});
				}
			},
			value: {
				handler(newD, oldD) {
					if (newD || oldD)
						this.v = 'value';
				},
				immediate: true
			},
			modelValue: {
				handler(newD, oldD) {
					if (newD || oldD)
						this.v = 'modelValue';
				},
				immediate: true
			},
		},
		computed: {
			mrange() {
				var mr = [];
				if (this.all)
					mr.push({
						id: 0,
						name: this.all
					});
				var tmprange = this.range;
				if (!this.isarray(this.range)) {
					tmprange = [];
					let oprang = (this.range + '').split('.');
					for (let r in oprang) {
						let idx = oprang[r].indexOf(':');
						if (idx <= 0)
							continue;
						tmprange.push({
							id: oprang[r].substring(0, idx),
							name: oprang[r].substring(idx + 1)
						});
					}
				}
				for (var i in tmprange) {
					if (this.chkuse && tmprange[i].isuse == 2)
						continue;
					if (tmprange[i].name.indexOf(this.searchval) > -1)
						mr.push(tmprange[i]);
				}
				return mr;
			},
			tvalue() {
				var val = '';
				if (this.v == 'modelValue') {
					if (typeof(this.modelValue) == 'number')
						val = this.modelValue;
					else if (this.modelValue)
						val = this.modelValue;
				} else if (this.v == 'value') {
					if (typeof(this.value) == 'number')
						val = this.value;
					else if (this.value)
						val = this.value;
				} else if (this.v instanceof Object) {
					return this.v;
				}
				for (var i in this.mrange) {
					if (this.mrange[i].id == val)
						return {
							index: i,
							...this.mrange[i]
						};
				}
				if (this.mrange.length > 0 && this.placeholder === '')
					return {
						index: 0,
						...this.mrange[0]
					};
				return {
					id: 0,
					index: -1,
					name: ''
				};
			}
		},
		mounted() {
			if (this.initevent) {
				this.$emit('change', {
					name: this.name,
					from: 'init',
					value: {
						...this.tvalue
					}
				});
			}
			this.lastvalue = {
				...this.tvalue
			};
		},
		methods: {
			searchconfirm(e) {
				this.$emit('search', {
					name: this.name,
					from: 'confirm',
					com: this,
					value: e.detail.value
				});
			},
			Selitem(index) {
				this.v = {
					index: index,
					...this.mrange[index]
				};
				this.$emit('update:modelValue', this.v.id);
				this.$emit('change', {
					name: this.name,
					from: 'select',
					value: {
						index: index,
						...this.v
					},
					lastvalue: this.lastvalue
				});
				this.lastvalue = {
					index: index,
					...this.v
				};
				this.hidepop();
			},
			hidepop() {
				var animation = uni.createAnimation({});
				animation.translateX('100vw');
				animation.opacity(0);
				animation.step({
					duration: 200
				});
				animation.height('auto');
				this.anidatapop = animation.export();
				setTimeout(() => {
					this.popclass = '';
				}, 300);
			},
			async showpop() {
				if (this.disabled)
					return;
				var app = getApp();
				app.globalData.scrollcbs['com_select'] = e => {
					delete app.globalData.scrollcbs['com_select'];
					this.hidepop();
				};
				const {
					headerheight,
					footerheight
				} = await this.com_gethdft();
				var fixtop = 0;

				this.searchval = '';
				this.popclass = 'temp';
				var mainrect = await this.getrect('._pop');
				if (!mainrect)
					return;
				var showrect = await this.getrect('._show');
				if (!showrect)
					return;
				var toph = showrect.top - headerheight - this.diastema;
				var btmh = app.globalData._sysinfo.windowHeight - footerheight - showrect.bottom - this.diastema;
				var topcls = '_btm';
				var syheight, sytop;
				if (toph > btmh) {
					topcls = '_top';
					syheight = mainrect.height;
					if (syheight > toph)
						syheight = toph;
					sytop = headerheight + fixtop + toph - syheight;
				} else {
					syheight = mainrect.height;
					if (syheight > btmh)
						syheight = btmh;
					sytop = showrect.bottom + this.diastema - fixtop;
				}
				this.popclass = topcls;
				this.$nextTick(() => {
					var animation = uni.createAnimation({});
					animation.translateX(0);
					animation.top(sytop);
					animation.height(syheight);
					animation.opacity(1);
					animation.step({
						duration: 200
					});
					this.anidatapop = animation.export();
					if (!this.tvalue.index)
						return;
					this.itemtop = 0;
					setTimeout(async () => {
						var listrect = await this.getrect('#select_list');
						var rect = await this.getrect('#selectitem-' + this.tvalue.index);
						if (!rect || !listrect)
							return;
						this.itemtop = rect.top - listrect.height / 2 - listrect.top;
					}, 200);
				});
			}

		}
	}
</script>
<style scoped>
	._select ._pop {
		position: fixed;
		display: flex;
		flex-direction: column;
		align-items: flex-start;
		opacity: 0;
		left: 0;
		right: 0;
		transform: translateX(100vw);
		transform: translateY(38px);
		z-index: 992;
	}

	._select ._pop ._search {
		background: var(--bg2);
		box-sizing: border-box;
		padding: 0.5em;
		width: 100%;
	}

	._select ._pop ._search>.itm {
		background: var(--bg1);
		border: 1px solid var(--bg4);
		border-radius: 0.5em;
		padding: 0.5em;
		text-align: left;
	}

	._select ._pop._top {
		justify-content: flex-end;
		flex-direction: column-reverse;
	}

	._select ._pop ._list {
		width: 100%;
		overflow: auto;
		text-align: left;
		background: var(--bg2);
	}

	._select ._pop ._list ._flex {
		display: flex;
		flex-direction: column;
		width: 100%;
		text-align: left;
		overscroll-behavior-y: contain !important;
		background: var(--bg2);
	}

	._select ._item._select {
		font-weight: bold;
		color: var(--man6);
	}

	._select ._pop ._list ._flex ._item {
		padding: 1em 1em;
		width: 100%;
		border-top: 1px solid var(--bg4);
	}

	._select ._pop ._list ._grid {
		display: grid;
		width: 100%;
		overflow: auto;
		text-align: left;
		background: var(--bg2);
	}

	._select ._pop ._list ._grid ._item {
		padding: 1em 1em;
		width: 100%;
		border-top: 1px solid var(--bg4);
	}

	._select ._pop ._list ._nodata {
		background: var(--bg2);
		text-align: center;
		padding: 2em 0 1em 0;
		color: var(--txt1);
	}

	._select {
		position: relative;
	}

	._select ._show {
		padding: 0;
		overflow: hidden;
		white-space: nowrap;
		text-overflow: ellipsis;
		display: flex;
		justify-content: flex-end;
		align-items: center;
	}

	._select ._show._left {
		justify-content: flex-start;
	}

	._select ._show._left ._txt {
		text-align: left;
	}

	._select ._show ._arrow {
		width: 1.5em;
		height: 1.5em;
		margin-left: 0.3em;
		transition: transform 0.3s;
	}

	._select ._show ._arrow._sel {
		transform: rotate(180deg);
	}

	._select ._mask {
		position: fixed;
		left: 0;
		right: 0;
		top: 0;
		bottom: 0;
		backgroundx: #f3abec99;
		z-index: 992;
		backdrop-filterx: blur(10px);
	}
</style>