<template>
	<view class="uni-datetime-picker">
		<view class="uni-date-editor" @click="initTimePicker">
			<slot>
				<view :class="{'uni-datetime-picker-disabled': disabled, 'uni-datetime-picker-timebox': border}">
					<view class="uni-date-x  ">
						<uni-icons type="calendar" color="#c0c4cc" size="22"></uni-icons>
						<view class="uni-date__x-input " :class="{'t-color':!time}"
							 >{{time||'请选择日期'}}</view> 
					</view> 
					<view v-if="showClearIcon" class="uni-date__icon-clear" @click.stop="clear">
						<uni-icons type="clear" color="#c0c4cc" size="24"></uni-icons>
					</view>
	
				</view>
			</slot>
		</view>
		<view v-if="visible" id="mask" class="uni-datetime-picker-mask" @click="tiggerTimePicker"></view>
		<view v-if="visible" class="uni-datetime-picker-popup" 
			:style="fixNvueBug">
			<view class="uni-title">
				<text class="uni-datetime-picker-text">请选择{{title}}</text>
			</view>
			<view class="uni-datetime-picker__container-box">
				<picker-view class="uni-datetime-picker-view" :indicator-style="indicatorStyle" :value="ym"
					@change="bindDateChange">
					<picker-view-column >
						<view class="uni-datetime-picker-item" v-for="(item,index) in years" :key="index">
							<text class="uni-datetime-picker-item">{{item}}</text>
						</view>
					</picker-view-column>
					<picker-view-column  v-if="!dateShow">
						<view class="uni-datetime-picker-item" v-for="(item,index) in months" :key="index">
							<text class="uni-datetime-picker-item">{{item}}</text>
						</view>
					</picker-view-column> 
				</picker-view>
				<!-- 兼容 nvue 不支持伪类 -->
				<text class="uni-datetime-picker-sign sign-left"  v-if="!dateShow">-</text>
			 
			</view>
			 
			<view class="uni-datetime-picker-btn">  
				<view class="uni-datetime-picker-btn-text" @click="tiggerTimePicker">
					 取消
				</view>
				<view @click="setTime" class="uni-datetime-picker-btn-text">
					 确定
				</view> 
			</view>
		</view>
	 
	</view>
</template>

<script>
 
	export default {
		name: 'UniDateYear',
		components: {
 
		},
		data() {
			return {
				indicatorStyle: `height: 50px;`,
				visible: false,
				fixNvueBug: {},
				dateShow: true, 
				title: '年份',
				// 输入框当前时间
				time: '',
				// 当前的年月 
				year: 1920,
				month: 0,
 
				// 起始时间
				startYear: 1920,
				startMonth: 1,
				 
				// 结束时间
				endYear: 2120,
				endMonth: 12,
				 
			}
		},
		props: { 
			value: {
				type: [String, Number],
				default: ''
			},
			modelValue: {
				type: [String, Number],
				default: ''
			},
			start: {
				type: [Number, String],
				default: ''
			},
			end: {
				type: [Number, String],
				default: ''
			},
			formatType: {
				type: String,
				default: 'string'
			},
			disabled: {
				type: [Boolean, String],
				default: false
			}, 
			border: {
				type: [Boolean],
				default: true
			},
			clearIcon: {
				type: [Boolean],
				default: true
			}, 
		},
		watch: {
			// #ifndef VUE3
			value: {
				handler(newVal, oldVal) {
					if (newVal) {
						this.parseValue(this.fixIosDateFormat(newVal)) //兼容 iOS、safari 日期格式
						this.initTime(false)
					} else {
						this.time = '' 
					}
				},
				immediate: true
			},
			// #endif
			// #ifdef VUE3
			modelValue: {
				handler(newVal, oldVal) { 
					if (newVal) {
						  this.parseValue(this.fixIosDateFormat(newVal)) //兼容 iOS、safari 日期格式
						  this.initTime(false)
					} else {
						this.time = '' 
					}
				},
				immediate: true
			},
			// #endif
			formatType: {
				handler(newValue) {
					if (newValue === 'year') { 
						this.dateShow=true;
						this.title = '年份'
					} else if (newValue === 'month') { 
						this.dateShow=false;
						this.title = '月份'
					}  
				},
				immediate: true
			},
			start: {
				handler(newVal) {
					if(newVal) this.parseDatetimeRange(this.fixIosDateFormat(newVal), 'start') //兼容 iOS、safari 日期格式
				},
				immediate: true
			},
			end: {
				handler(newVal) {
					if(newVal) this.parseDatetimeRange(this.fixIosDateFormat(newVal), 'end') //兼容 iOS、safari 日期格式
				},
				immediate: true
			},

			// 月 可选范围变化后，检查当前值是否在范围内，不在则当前值重置为可选范围第一项
			months(newVal) {
				this.checkValue('month', this.month, newVal)
			}, 
		},
		computed: {
			// 当前年、月、日、时、分、秒选择范围
			years() {
				return this.getCurrentRange('year')
			},

			months() {
				return this.getCurrentRange('month')
			},

			showClearIcon() {
				const {
					clearIcon,
					disabled,
					time 
				} = this
				const bool = clearIcon && !disabled && time 
				return bool
			},
			// picker 当前值数组
			ym() {
				return [this.year - this.minYear, this.month - this.minMonth]
			}, 
 
			// 当前年、月、日、时、分、秒的最小值和最大值
			minYear() {
				return this.startYear
			},
			maxYear() {
				return this.endYear
			},
			minMonth() {
				if (this.year === this.startYear) {
					return this.startMonth
				} else {
					return 1
				}
			},
			maxMonth() {
				if (this.year === this.endYear) {
					return this.endMonth
				} else {
					return 12
				}
			}, 
   
		},

		mounted() {
			// #ifdef APP-NVUE
			const res = uni.getSystemInfoSync();
			this.fixNvueBug = {
				top: res.windowHeight / 2,
				left: res.windowWidth / 2
			}
			// #endif
		},

		methods: {
			/**
			 * @param {Object} item
			 * 小于 10 在前面加个 0
			 */

			lessThanTen(item) {
				return item < 10 ? '0' + item : item
			},
 

			/**
			 * 解析选择器初始值，类型可以是字符串、时间戳，例如：2000-10-02、'08:30:00'、 1610695109000
			 * @param {String | Number} datetime
			 */
			initPickerValue(datetime) {
				let defaultValue = null
				if (datetime) {
					defaultValue = this.compareValueWithStartAndEnd(datetime, this.start, this.end)
				} else {
					defaultValue = Date.now()
					defaultValue = this.compareValueWithStartAndEnd(defaultValue, this.start, this.end)
				} 
				this.parseValue(defaultValue)
			},

			/**
			 * 初始值规则：
			 * - 用户设置初始值 value
			 * 	- 设置了起始时间 start、终止时间 end，并 start < value < end，初始值为 value， 否则初始值为 start
			 * 	- 只设置了起始时间 start，并 start < value，初始值为 value，否则初始值为 start
			 * 	- 只设置了终止时间 end，并 value < end，初始值为 value，否则初始值为 end
			 * 	- 无起始终止时间，则初始值为 value
			 * - 无初始值 value，则初始值为当前本地时间 Date.now()
			 * @param {Object} value
			 * @param {Object} dateBase
			 */
			compareValueWithStartAndEnd(value, start, end) {
				let winner = null
				value = this.superTimeStamp(value) 
				start = this.superTimeStamp(start)
				end = this.superTimeStamp(end)

				if (start && end) {
					if(!value){
						winner = Date.now()
					}else if (start<value&&value<end) {
						winner = new Date(start)
					} else{
						winner = new Date(value)
					} 
				} else if (start && !end) {
					winner = start <  value ? new Date(value) : new Date(start)
				} else if (!start && end) {
					winner = value <  end ? new Date(value) : new Date(end)
				} else if(!start && !end){
					winner = new Date(value)
				}else{
					winner = Date.now()
				}

				return winner
			},

			/**
			 * 转换为可比较的时间戳，接受日期、时分秒、时间戳
			 * @param {Object} value
			 */
			superTimeStamp(value) {
				let dateBase = '' ; 
				if (!this.time ) {
					const now = new Date()
					const year = now.getFullYear()
					const month = now.getMonth() + 1 
					dateBase = year + '/' + month + '/'  
				}
				return this.createTimeStamp(dateBase + value)
			},

			/**
			 * 解析默认值 value，字符串、时间戳
			 * @param {Object} defaultTime
			 */
			parseValue(value) {  
				if (!value) {
					return
				}  
				let defaultDate = new Date(value)   
				this.year = defaultDate.getFullYear()
				this.month = defaultDate.getMonth() + 1    
			},

			/**
			 * 解析可选择时间范围 start、end，年月日字符串、时间戳
			 * @param {Object} defaultTime
			 */
			parseDatetimeRange(point, pointType) {
				// 时间为空，则重置为初始值
				if (!point) {
					if (pointType === 'start') {
						this.startYear = 1920
						this.startMonth = 1
			 
					}
					if (pointType === 'end') {
						this.endYear = 5000
						this.endMonth = 12
			 
					}
					return
				}
	 
				if (!point) {
					pointType === 'start' ? this.startYear = this.year - 60 : this.endYear = this.year + 60
					return
				}
				if (Number(point) && Number(point) !== NaN) {
					point = parseInt(point)
				}

				const pointDate = new Date(point)
				this[pointType + 'Year'] = pointDate.getFullYear()
				this[pointType + 'Month'] = pointDate.getMonth() + 1 
	 
		 
			},

			// 获取 年、月、日、时、分、秒 当前可选范围
			getCurrentRange(value) {
				const range = []
				for (let i = this['min' + this.capitalize(value)]; i <= this['max' + this.capitalize(value)]; i++) {
					range.push(i)
				}
				return range
			},

			// 字符串首字母大写
			capitalize(str) {
				return str.charAt(0).toUpperCase() + str.slice(1)
			},

			// 检查当前值是否在范围内，不在则当前值重置为可选范围第一项
			checkValue(name, value, values) {
				if (values.indexOf(value) === -1) {
					this[name] = values[0]
				}
			},
 

			//兼容 iOS、safari 日期格式
			fixIosDateFormat(value) { 
				if(!value) return value;
				if (typeof value === 'string') {
					value = value.replace(/-/g, '/')
				}else{
					if(this.dateShow){
						value= value+'/01/01 00:00:00' 
					}else{
						value = value.replace(/-/g, '/')+'/01 00:00:00' 
					} 
				} 
				return value
			},

			/**
			 * 生成时间戳
			 * @param {Object} time
			 */
			createTimeStamp(time) { 
				if (!time) return
				if (typeof time === "number") {
					return time
				} else {
					time = time.replace(/-/g, '/') 
					return Date.parse(time)
				}
			},
 
			/**
			 * 生成日期或时间的字符串
			 */
			createDomSting() {   
				if (this.formatType=='year') { 
					return this.year
				} else if (this.formatType=='month'){
					return this.year +'-' +this.lessThanTen(this.month)
				}else {
					return ''
				}
			},

			/**
			 * 初始化返回值，并抛出 change 事件
			 */
			initTime(emit = true) {
				this.time = this.createDomSting()
				if (!emit) return  
				 this.$emit('change', this.time)
				 this.$emit('input', this.time)
				 this.$emit('update:modelValue', this.time)
			},

			/**
			 * 用户选择日期或时间更新 data
			 * @param {Object} e
			 */
			bindDateChange(e) {
				const val = e.detail.value 
				this.year = this.years[val[0]]
				this.month = this.months[val[1]]  
			}, 

			/**
			 * 初始化弹出层
			 */
			initTimePicker() {
				if (this.disabled) return 
				const value = this.fixIosDateFormat(this.value||this.modelValue)
				this.initPickerValue(value)
				this.visible = !this.visible
			},

			/**
			 * 触发或关闭弹框
			 */
			tiggerTimePicker(e) {
				this.visible = !this.visible
			},

			/**
			 * 用户点击“清空”按钮，清空当前值
			 */
			clearTime() {
				this.time = ''
				this.$emit('change', this.time)
				this.$emit('input', this.time)
				this.$emit('update:modelValue', this.time)
				this.tiggerTimePicker()
			},

			/**
			 * 用户点击“确定”按钮
			 */
			setTime() {
				this.initTime()
				this.tiggerTimePicker()
			},
			clear(needEmit = true) { 
				this.time = ''  
				if (needEmit) { 
					this.$emit('input', '')
					this.$emit('update:modelValue', '')
					this.$emit('change', '')
					this.$emit('blur', '')
				}  
			},
		}
	}
</script>

<style lang="scss">
	$uni-primary: #007aff !default;

	.uni-datetime-picker {
		/* #ifndef APP-NVUE */
		/* width: 100%; */
		/* #endif */
	}
	.uni-date-x {
		display: flex;
		flex-direction: row;
		align-items: center;
		justify-content: center;
		padding: 0 10px;
		border-radius: 4px; 
		color: #000;
		font-size: 14px;
		flex: 1;
	}
	.uni-date__x-input {
		padding: 0 8px;
		/* #ifndef APP-NVUE */
		width: auto;
		/* #endif */
		position: relative;
		overflow: hidden;
		flex: 1;
		display: flex;
		align-items: center;
		font-size: 14px;
		height: 35px;
	}
	.t-color{
		color:gray
	}
	.uni-date__icon-clear {
		padding: 0 5px;
		display: flex;
		align-items: center;
		/* #ifdef H5 */
		cursor: pointer;
		/* #endif */
	}
	.uni-datetime-picker-view {
		height: 130px;
		width: 270px;
		/* #ifndef APP-NVUE */
		cursor: pointer;
		/* #endif */
	}

	.uni-datetime-picker-item {
		height: 50px;
		line-height: 50px;
		text-align: center;
		font-size: 14px;
	}

	.uni-datetime-picker-btn {
		margin-top: 60px;
		/* #ifndef APP-NVUE */
		display: flex;
		cursor: pointer;
		/* #endif */
		flex-direction: row;
		justify-content: space-between;
	}

	.uni-datetime-picker-btn-text {
		font-size: 14px;
		color: $uni-primary;
	}
  
	.uni-datetime-picker-mask {
		position: fixed;
		bottom: 0px;
		top: 0px;
		left: 0px;
		right: 0px;
		background-color: rgba(0, 0, 0, 0.4);
		transition-duration: 0.3s;
		z-index: 998;
	}

	.uni-datetime-picker-popup {
		border-radius: 8px;
		padding: 30px;
		width: 270px;
		/* #ifdef APP-NVUE */
		height: 500px;
		/* #endif */
		/* #ifdef APP-NVUE */
		width: 330px;
		/* #endif */
		background-color: #fff;
		position: fixed;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		transition-duration: 0.3s;
		z-index: 999;
	}
 
	.uni-datetime-picker-time {
		color: grey;
	} 
	.uni-datetime-picker-timebox {
		display: flex;
    align-items: center;
		border: 1px solid #E5E5E5;
		border-radius: 5px; 
		/* #ifndef APP-NVUE */
		box-sizing: border-box;
		cursor: pointer;
		/* #endif */
	} 
	.uni-datetime-picker-disabled {
		border-color: rgb(242, 242, 242);
		background-color: rgb(247, 246, 246);
		opacity: 0.4;
		/* #ifdef H5 */
		cursor: not-allowed !important;
		/* #endif */
	}

	.uni-datetime-picker-text {
		font-size: 14px; 
	}

	.uni-datetime-picker-sign {
		position: absolute;
		top: 53px;
		/* 减掉 10px 的元素高度，兼容nvue */
		color: #999;
		/* #ifdef APP-NVUE */
		font-size: 16px;
		/* #endif */
	}

	.sign-left {
		left: 50%;
	} 
	.uni-datetime-picker__container-box {
		position: relative;
		display: flex;
		align-items: center;
		justify-content: center;
		margin-top: 40px;
	}

 
</style>
