<template>
	<view style="width: 100%;" :style="{height}">
		<input type="hidden" :name="name" :value="tostamp(tvalue)" style="display:none;" />
		<input v-if="hasmore" type="hidden" :name="name+'_date'" :value="todatetime(tvalue,'d')" style="display:none;" />
		<view class="yearmonth" :style="{padding:selectmonth?'0 1.5em':''}">
			<view class="itm">
				<view v-if="selectmonth" @tap="asyear(-10)" class="flex" style="padding-right:2em;">
					<view class="arrow left ciy-icon-arrow" style="margin-right:-1em;"></view>
					<view class="arrow left ciy-icon-arrow" style="margin-right:-1em;"></view>
				</view>
				<view class="arrow left ciy-icon-arrow" @tap="asyear(-1)"></view>
				<view class="maintxt" @tap="chgpage(1)">{{year}} {{lang('calendar.year')}}</view>
				<view class="arrow right ciy-icon-arrow" @tap="asyear(1)"></view>

				<view v-if="selectmonth" @tap="asyear(10)" class="flex" style="padding-left:2em;">
					<view class="arrow right ciy-icon-arrow" style="margin-left:-1em;"></view>
					<view class="arrow right ciy-icon-arrow" style="margin-left:-1em;"></view>
				</view>
			</view>
			<view class="itm" v-if="!selectmonth">
				<view class="arrow left ciy-icon-arrow" @tap="asmonth(-1)"></view>
				<view class="maintxt" @tap="chgpage(2)">{{month+1}} {{lang('calendar.month')}}</view>
				<view class="arrow right ciy-icon-arrow" @tap="asmonth(1)"></view>
			</view>
			<view class="itm" v-else>
			</view>
			<view v-if="!selectmonth" class="itm today" @tap="today">{{lang('calendar.today')}}</view>
			<view v-else class="itm today" @tap="today">{{lang('calendar.tomonth')}}</view>
		</view>
		<view v-if="cpage == 0" style="padding: 0 0.2em;position: relative;">
			<view class="week">
				<view class="itm" v-for="(w,index) in weeks">
					<slot name="header" :itm="{week:w}">
						<view class="defweek">
							<view class="itm" :style="{borderLeftColor:index?bordercolor:''}">
								{{lang('week.'+w)}}
							</view>
						</view>
					</slot>
				</view>
			</view>
			<ciy-gesture @toleft="asmonth(1)" @toright="asmonth(-1)">
				<view class="days">
					<view class="itm" v-for="item in dayarr" @tap="clksel(item)">
						<slot name="data" :itm="{year:year,month:month+1,day:item,date:tvalue,select:cal_valueselect(item),cansel:cal_opminmax(item)}">
							<view class="defday" :style="cal_valueselect(item)?'color:' + selecttextcolor + ';background:' + selectbg + ';border:1px solid ' + bordercolor:''">
								<view :style="{opacity:cal_opminmax(item)?1:0.4}">{{item}}</view>
							</view>
						</slot>
					</view>
				</view>
			</ciy-gesture>
			<view style="position: absolute;bottom:0.8em;right:0.5em;" v-if="clearbtn">
				<button class="btn def" @tap="clknodate">{{lang('calendar.nodate')}}</button>
			</view>
		</view>
		<view v-if="cpage == 1" class="syear">
			<view v-if="!selectmonth" class="itm lr" @tap="odyear(-10)">
				<view class="arrow left ciy-icon-arrow"></view>
				<view class="arrow left ciy-icon-arrow"></view>
			</view>
			<view v-if="!selectmonth" class="itm lr" @tap="odyear(10)">
				<view class="arrow right ciy-icon-arrow"></view>
				<view class="arrow right ciy-icon-arrow"></view>
			</view>
			<view class="itm" v-for="yy in 12" @tap="clkyear(startyear+yy)" :style="startyear+yy==year?'font-weight:bolder;color:' + selecttextcolor:''">
				{{startyear+yy}}
			</view>
		</view>
		<view v-if="cpage == 2" class="smonth">
			<view class="itm" v-for="mon in 12" @tap="clkmon(mon)" :style="month+1==mon?'font-weight:bolder;color:' + selecttextcolor:''">
				{{mon}} {{lang('calendar.month')}}
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		behaviors: ['uni://form-field-group'],
		emits: ['change', 'update:modelValue', 'viewchange'],
		props: {
			name: {
				type: String
			},
			modelValue: {
				type: [String, Number, Date],
				default: ''
			},
			value: {
				type: [String, Number, Date],
				default: ''
			},
			initevent: {
				type: Boolean,
				default: false
			},
			hasmore: {
				type: Boolean,
				default: false
			},
			bordercolor: {
				type: String,
				default: 'var(--bg6)'
			},
			selecttextcolor: {
				type: String,
				default: 'var(--man5)'
			},
			selectbg: {
				type: String,
				default: 'var(--bg1)'
			},
			height: {
				type: String,
				default: '23em'
			},
			selectmonth: {
				type: Boolean,
				default: false
			},
			weekmonday: {
				type: Boolean,
				default: false
			},
			mindate: {
				type: [String, Number, Date],
				default: ''
			},
			maxdate: {
				type: [String, Number, Date],
				default: ''
			},
			clearbtn: {
				type: Boolean,
				default: false
			},
		},
		data() {
			return {
				v: '',
				startyear: 0,
				year: 0,
				month: 0,
				cpage: 0 //0日期，1年，2月
			};
		},
		watch: {
			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: {
			tvalue() {
				var val = '';
				if (this.v == 'modelValue') {
					if (typeof(this.modelValue) == 'number')
						val = new Date(this.modelValue * 1000);
					else if (this.modelValue)
						val = this.modelValue;
				} else if (this.v == 'value') {
					if (typeof(this.value) == 'number')
						val = new Date(this.value * 1000);
					else if (this.value)
						val = this.value;
				} else {
					val = this.v;
				}
				this._is0 = false;
				if (!(val instanceof Date)) {
					if (val.indexOf('-') > -1 || val.indexOf('/') > -1) {
						val = this.str2date(val);
					} else {
						val = this.toint(val);
						if (val == 0) {
							this._is0 = true;
							val = new Date();
						} else {
							val = new Date(val * 1000);
						}
					}
				} else if (isNaN(val.getTime())) {
					this._is0 = true;
					val = new Date();
				}

				if (this.max && this.max <= val)
					val = this.max;

				if (this.min && this.min >= val && val.getTime() != 0)
					val = this.min;
				if (val.getTime() != 0) {
					this.year = val.getFullYear();
					this.month = val.getMonth();
				}
				return val;
			},
			max() {
				var val = this.maxdate;
				if (val instanceof Date) {
					if (isNaN(val.getTime()))
						val = null;
				} else if (typeof(val) == 'number') {
					val = new Date(val * 1000);
				} else if (val.indexOf('-') > -1 || val.indexOf('/') > -1) {
					val = this.str2date(val);
				} else if (val == 'now') {
					val = new Date();
				} else {
					val = this.toint(val);
					if (val == 0)
						val = null;
					else {
						val = new Date(val * 1000);
					}
				}
				return val;
			},
			min() {
				var val = this.mindate;
				if (val instanceof Date) {
					if (isNaN(val.getTime()))
						val = null;
				} else if (typeof(val) == 'number') {
					val = new Date(val * 1000);
				} else if (val.indexOf('-') > -1 || val.indexOf('/') > -1) {
					val = new Date(val);
				} else if (val == 'now') {
					val = new Date();
				} else {
					val = this.toint(val);
					if (val == 0)
						val = null;
					else {
						val = new Date(val);
					}
				}
				return val;
			},
			weeks() {
				var wks = [];
				if (!this.weekmonday)
					wks.push(0);
				wks.push(1);
				wks.push(2);
				wks.push(3);
				wks.push(4);
				wks.push(5);
				wks.push(6);
				if (this.weekmonday)
					wks.push(0);
				return wks;
			},
			dayarr() {
				if (this.year == 0)
					return;
				var darr = [];
				var monthdaycnt = new Date(this.year, this.month + 1, 0).getDate();
				var day1 = new Date(this.year, this.month, 1);
				var week = day1.getDay();
				if (this.weekmonday)
					week--;
				for (var i = 0; i < week; i++)
					darr.push('');
				for (var i = 1; i <= monthdaycnt; i++)
					darr.push(i);
				var nt = 7 - (darr.length % 7);
				for (var i = darr.length; i < 42; i++)
					darr.push('');
				return darr;
			}
		},
		mounted() {
			this.year = this.tvalue.getFullYear();
			this.month = this.tvalue.getMonth();
			if (this.initevent) {
				this.$emit('change', {
					name: this.name,
					from: 'init',
					value: this.tostamp(this.tvalue),
					date: this.tvalue
				});
			}
			if (this.selectmonth)
				this.cpage = 2;
		},
		methods: {
			clkyear(y) {
				if (this.selectmonth) {
					if (this.year != y)
						this.month = -1;
					this.year = y;
					this.cpage = 2;
					return;
				}
				this.year = y;
				this.cpage = 0;
				this.$emit('viewchange', {
					name: this.name,
					from: 'year',
					month: this.month,
					year: this.year
				});
			},
			clkmon(mon) {
				this.month = mon - 1;
				if (this.selectmonth) {
					this.clksel(1);
					return;
				}
				this.cpage = 0;
				this.$emit('viewchange', {
					name: this.name,
					from: 'month',
					month: this.month,
					year: this.year
				});
			},
			chgpage(p) {
				var page = this.cpage == p ? (this.selectmonth ? 2 : 0) : p;
				if (page == 1)
					this.startyear = parseInt((this.year - 1) / 10) * 10;
				this.cpage = page;
			},
			odyear(od10) {
				this.startyear += od10;
			},
			asyear(od) {
				this.year += od;
				if (this.selectmonth) {
					this.cpage = 2;
					this.month = -1;
					return;
				}
				this.cpage = 0;
				this.$emit('viewchange', {
					name: this.name,
					from: 'year',
					month: this.month,
					year: this.year
				});
			},
			asmonth(od) {
				this.month += od;
				if (this.month < 0) {
					this.year--;
					this.month = 11;
				}
				if (this.month > 11) {
					this.year++;
					this.month = 0;
				}

				this.$emit('viewchange', {
					name: this.name,
					from: 'month',
					month: this.month,
					year: this.year
				});
				this.cpage = 0;
			},
			today(od) {
				var val = new Date();
				if (this.max && this.max <= val)
					val = this.max;
				if (this.min && this.min >= val)
					val = this.min;
				this.v = val;
				this.year = val.getFullYear();
				this.month = val.getMonth();
				val.setHours(0);
				val.setMinutes(0); //val.getTimezoneOffset()
				val.setSeconds(0);
				//var vt = this.tostamp(val);
				// this.$emit('update:modelValue', vt);
				// this.$emit('change', {
				// 	name: this.name,
				// 	from: 'today',
				// 	value: vt,
				// 	date: val
				// });
				if (this.selectmonth)
					this.clksel(1);
				else
					this.clksel(val.getDate());
			},
			cal_opminmax(day) {
				var date = new Date(this.year, this.month, day);
				if (this.max) {
					if (date > this.max)
						return false;
				}
				if (this.min) {
					if (date < this.min)
						return false;
				}
				return true;
			},
			cal_valueselect(day) {
				if (this._is0)
					return false;
				if (this.tvalue.getFullYear() != this.year)
					return false;
				if (this.tvalue.getMonth() != this.month)
					return false;
				if (this.tvalue.getDate() != day)
					return false;
				return true;
			},
			clknodate() {
				var date = new Date(0);
				this.$emit('update:modelValue', 0);
				this.$emit('change', {
					name: this.name,
					from: 'nodate',
					value: 0,
					date: date
				});
				this.v = date;
			},
			clksel(day) {
				if (!day)
					return;
				var date = new Date(this.year, this.month, day);
				if (this.max) {
					if (date > this.max)
						return;
				}
				if (this.min) {
					if (date < this.min)
						return;
				}
				var val = this.tostamp(date);
				this.$emit('update:modelValue', val);
				this.$emit('change', {
					name: this.name,
					from: 'click',
					value: val,
					date: date
				});
				this.v = date;
			}
		}
	}
</script>
<style scoped>
	.syear {
		display: flex;
		flex-wrap: wrap;
	}

	.syear>.itm {
		text-align: center;
		flex: 0 0 25%;
		line-height: 6em;
	}

	.syear .lr {
		flex: 0 0 50%;
		line-height: 2em;
		margin-bottom: -1em;
		padding-top: 1em;
	}

	.smonth {
		display: flex;
		flex-wrap: wrap;
		line-height: 6em;
	}

	.smonth>.itm {
		text-align: center;
		flex: 0 0 25%;
	}

	.week {
		display: flex;
	}

	.week>.itm {
		flex: 1;
		text-align: center;
	}

	.week .defweek {
		padding: 0.5em 0;
	}

	.week .defweek>.itm {
		font-weight: bolder;
		border-left: 1px solid transparent;
	}

	.days {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
	}

	.days .itm {
		text-align: center;
		flex: 0 0 14.28%;
	}

	.days .defday {
		height: 3em;
		display: flex;
		flex-direction: column;
		justify-content: center;
		align-items: center;
		border-radius: 0.5em;
	}

	.yearmonth {
		display: flex;
		height: 3em;
		gap: 1em;
	}

	.yearmonth>.itm {
		flex: 1;
		display: flex;
		align-items: center;
	}

	.yearmonth .today {
		flex: none;
		padding-right: 0.5em;
		white-space: nowrap;
	}

	.yearmonth .maintxt {
		flex: 1;
		text-align: center;
		white-space: nowrap;
	}

	.arrow {
		width: 1.5em;
		height: 1.5em;
		display: inline-block;
	}

	.arrow.left {
		transform: rotate(90deg);
	}

	.arrow.right {
		transform: rotate(-90deg);
	}
</style>