import { Lunar, LunarInfoType } from './calendar';

export type DateType = {
	fullDate : string;
	year : number;
	month : number;
	date : number;
	hour : number;
	minute : number;
	second : number;
	millisecond : number;
	day : number;
	isToday : boolean;
	lunar : string;
};

export type DateInfo = {
	year : number,
	month : number,
	day : number,
	hours : number,
	minutes : number,
	seconds : number,
	milliseconds : number
};

export class DateUtil {
	private lunar : Lunar;

	private static readonly dateRegex = /^(\d{4})[-/](\d{1,2})[-/](\d{1,2})(?:[ T](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d{1,3}))?)?)?(?:[ ]?(Z|[+-]\d{2}:\d{2}))?$/;


	constructor() {
		this.lunar = new Lunar();
	};

	/**
	 * 计算阴历日期显示
	 */
	getlunar(year : number, month : number, date : number) : LunarInfoType {
		return this.lunar.solar2lunar(year, month, date)
	}

	/**
	 * 解析时间戳
	 */
	parseTimestamp(timestamp : number) : DateInfo {
		let mTimestamp : number = timestamp;
		// 定义每个时间单位的毫秒数
		const millisecondsPerSecond : number = 1000;
		const millisecondsPerMinute = 60 * millisecondsPerSecond;
		const millisecondsPerHour = 60 * millisecondsPerMinute;
		const millisecondsPerDay = 24 * millisecondsPerHour;

		// 计算总天数
		let totalDays = Math.floor(mTimestamp / millisecondsPerDay);
		mTimestamp -= totalDays * millisecondsPerDay;

		// 计算年、月、日
		const startYear : number = 1970;
		let year = startYear;
		let month : number = 0;
		let day : number = 0;

		// 计算当前年是否为闰年
		const isLeapYear = (year : number) : boolean => (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;

		// 计算年份
		while (true) {
			const daysInYear = isLeapYear(year) ? 366 : 365;
			if (totalDays >= daysInYear) {
				totalDays -= daysInYear;
				year++;
			} else {
				break;
			}
		}

		// 计算月份
		const daysInMonth = [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
		for (month = 0; month < daysInMonth.length; month++) {
			if (totalDays < daysInMonth[month]) {
				break;
			}
			totalDays -= daysInMonth[month];
		}
		month++; // 月份是从0开始的，所以需要+1
		day = totalDays + 1; // 加1是因为总天数已经减去了一整天的毫秒数

		// 计算小时、分钟、秒
		const hours = Math.floor(mTimestamp / millisecondsPerHour) % 24;
		mTimestamp -= hours * millisecondsPerHour;
		const minutes = Math.floor(mTimestamp / millisecondsPerMinute) % 60;
		mTimestamp -= minutes * millisecondsPerMinute;
		const seconds = Math.floor(mTimestamp / millisecondsPerSecond) % 60;
		const milliseconds = mTimestamp % millisecondsPerSecond;

		return {
			year,
			month,
			day,
			hours,
			minutes,
			seconds,
			milliseconds
		} as DateInfo;
	}

	/**
	 * 获取任意时间
	 */
	getDate(date : string) : DateType {
		let dd : Date = new Date();

		// 使用正则表达式解析日期和时间
		const match = date.match(DateUtil.dateRegex);
		if (match != null && match[1] != null && match[2] != null && match[3] != null && match.length > 0) {
			// 解构匹配结果
			// const [_, year, month, day, hour, minute, second, milllisceond] = match;
			const yearR = parseInt(match[1]!, 10);
			const monthR = parseInt(match[2]!, 10);
			const dayR = parseInt(match[3]!, 10);
			let hourR = 0;
			if (match.length >= 5 && match[4] != null) {
				hourR = parseInt(match[4]!, 10);
			}
			let minuteR = 0;
			if (match.length >= 6 && match[5] != null) {
				minuteR = parseInt(match[5]!, 10);
			}
			let secondR = 0;
			if (match.length >= 7 && match[6] != null) {
				secondR = parseInt(match[6]!, 10);
			}
			let millisceondR = 0;
			if (match.length >= 8 && match[7] != null) {
				millisceondR = parseInt(match[7]!, 10);
			}
			let timezoneOffset: string | null = null;
			if (match.length >= 9 && match[8] != null) {
				timezoneOffset = match[8];
			}

			// 创建 Date 对象
			dd = new Date(yearR, monthR - 1, dayR, hourR, minuteR, secondR, millisceondR);

			// 应用时区偏移
			if (timezoneOffset != null && timezoneOffset != 'Z') {
				const offsetSign = (timezoneOffset.split(''))[0] == '+' ? 1 : -1;
				const offsetHours = 8 - parseInt(timezoneOffset.substring(1, 3), 10);
				const offsetMinutes = parseInt(timezoneOffset.substring(4, 6), 10);
				const offsetMilliseconds = (offsetHours * 60 + offsetMinutes) * 60 * 1000 * offsetSign;
				dd = new Date(dd.getTime() + offsetMilliseconds);
			}
		}

		const y = dd.getFullYear();
		const m = dd.getMonth() + 1;
		const d = dd.getDate();
		const h = dd.getHours();
		const M = dd.getMinutes();
		const s = dd.getSeconds();
		const ms = dd.getMilliseconds();

		let nowDate = y + '-' + m + '-' + d;
		const lunarData = this.getlunar(y, m, d);

		const data : DateType = {
			fullDate: nowDate,
			year: y,
			month: m,
			date: d,
			hour: h,
			minute: M,
			second: s,
			millisecond: ms,
			day: dd.getDay() + 1,
			lunar: lunarData.IDayCn,
			isToday: this.getlunar(y, m, d).isToday
		};

		return data;
	};
};