<template>
	<view class="jnpf-calculation jnpf-calculation-right">
		<u-input input-align='right' :modelValue="jnpf.toDate(innerValue, format)" disabled placeholder='' />
	</view>
</template>
<script>
	import {
		dayjs
	} from '@/uni_modules/iRainna-dayjs/js_sdk/dayjs.min.js'

	const calcRPN = rpnExps => {
		rpnExps = rpnExps.concat()
		const calc = (x, y, type) => {
			let a1 = Number(x),
				a2 = Number(y)
			switch (type) {
				case '+':
					return a1 + a2;
				case '-':
					return a1 - a2;
				case '×':
					return a1 * a2;
				case '÷':
					return a1 / a2;
			}
		}
		for (let i = 2; i < rpnExps.length; i++) {
			if ('+-×÷'.includes(rpnExps[i])) {
				let val = calc(rpnExps[i - 2], rpnExps[i - 1], rpnExps[i])
				rpnExps.splice(i - 2, 3, val)
				i = i - 2
			}
		}
		return rpnExps[0]
	}
	const mergeNumberOfExps = expressions => {
		const res = []
		const isNumChar = n => /^[\d|\.]$/.test(n)
		for (let i = 0; i < expressions.length; i++) {
			if (i > 0 && isNumChar(expressions[i - 1]) && isNumChar(expressions[i])) {
				res[res.length - 1] += expressions[i]
				continue
			}
			res.push(expressions[i])
		}
		return res
	}
	export default {
		name: 'jnpf-date-calculation',
		props: {
			modelValue: {
				type: [String, Number],
				default: ''
			},
			expression: {
				type: Array,
				default: []
			},
			formData: {
				type: Object,
				default: {}
			},
			rowIndex: {
				type: [String, Number],
				default: ''
			},
			startRelationField: String,
			startTimeValue: [String, Number],
			startTimeType: {
				default: 1,
				type: Number,
			},
			format: {
				default: 'yyyy-MM-dd',
				type: String,
			},
		},
		data() {
			return {
				innerValue: '',
				startTime: new Date(),
			}
		},
		computed: {
			getExp() {
				return mergeNumberOfExps(this.expression)
			},
		},
		watch: {
			formData: {
				handler(val, oldVal) {
					setTimeout(() => {
						this.execRPN()
					}, 0)
				},
				deep: true,
				immediate: true
			},
			modelValue: {
				handler(val, oldVal) {
					this.innerValue = val
				},
				deep: true,
				immediate: true
			},
		},
		methods: {
			/**
			 * 计算表达式
			 */
			execRPN() {
				const temp = this.getExp.map(t => typeof t === 'object' ? this.getFormVal(t.__vModel__) : t)
				if (this.startTimeType == 1) this.startTime = this.startTimeValue;
				if (this.startTimeType == 2) this.startTime = this.getFormVal(this.startRelationField);
				this.innerValue = this.calcDate(this.startTime, this.getDateInfo(temp));
				this.$emit('update:modelValue', this.innerValue)
			},
			getDateInfo(exp) {
				let days = 0;
				let months = 0;
				let years = 0;
				let hours = 0;
				let minutes = 0;
				let seconds = 0;
				for (let i = 0; i < exp.length; i += 3) {
					const sign = exp[i];
					const value = Number.parseInt(exp[i + 1], 10);
					const unit = exp[i + 2];
					const factor = sign === '+' ? 1 : -1;
					switch (unit) {
						case 'd': {
							days += factor * value;
							break;
						}
						case 'h': {
							hours += factor * value;
							break;
						}
						case 'M': {
							months += factor * value;
							break;
						}
						case 'm': {
							minutes += factor * value;
							break;
						}
						case 's': {
							seconds += factor * value;
							break;
						}
						case 'Y': {
							years += factor * value;
							break;
						}
					}
				}
				return {
					days,
					hours,
					minutes,
					months,
					seconds,
					years
				};
			},
			calcDate(date, change) {
				if (!date) return '';
				const newDate = new Date(date);
				newDate.setFullYear(newDate.getFullYear() + change.years);
				newDate.setMonth(newDate.getMonth() + change.months);
				newDate.setDate(newDate.getDate() + change.days);
				newDate.setHours(newDate.getHours() + change.hours);
				newDate.setMinutes(newDate.getMinutes() + change.minutes);
				newDate.setSeconds(newDate.getSeconds() + change.seconds);
				return dayjs(newDate).startOf(this.jnpf.getDateTimeUnit(this.format)).valueOf();
			},
			/**
			 * 获取指定组件的值
			 */
			getFormVal(vModel) {
				try {
					if (vModel.indexOf('.') > -1) {
						let [tableVModel, cmpVModel] = vModel.split('.');
						if (typeof this.rowIndex === 'number') {
							if (!Array.isArray(this.formData[tableVModel]) || this.formData[tableVModel].length < this
								.rowIndex + 1) return 0;
							return this.formData[tableVModel][this.rowIndex][cmpVModel] || 0;
						} else {
							if (!this.formData[tableVModel].length) return 0;
							return this.formData[tableVModel].reduce((sum, c) => (c[cmpVModel] ? Number(c[cmpVModel]) :
								0) + sum, 0);
						}
					}
					return this.formData[vModel] || 0
				} catch (error) {
					console.warn('计算公式出错, 可能包含无效的组件值', error)
					return 0
				}
			},
		}
	}
</script>

<style lang="scss" scoped>
	.jnpf-calculation {
		width: 100%;

		&.jnpf-calculation-right {
			text-align: right;
		}

		.tips {
			color: #999999;
			line-height: 40rpx;
		}

		.unit {
			padding-left: 10rpx;
		}
	}
</style>