<template>
    <div class="diy-calendar-wrapper">
        <div class="calendar-header">
            <!-- 左箭头 -->
            <div class="left-arrow" @click="jumpMonth(-1)">
                <svg width="30" height="30">
                    <path d="M 19,9 L 11,15 18,21" stroke="rgba(95,147,238,0.9)" fill="none" stroke-width="2"
                        stroke-linecap="round" stroke-linejoin="round" />
                </svg>
            </div>
            <!-- 年月标题 -->
            <div class="center-title">{{ targetDateFormat }}</div>
            <!-- 右箭头 -->
            <div class="right-arrow" @click="jumpMonth(1)">
                <svg width="30" height="30">
                    <path d="M 11,9 L 18,15 11,21" stroke="rgba(95,147,238,0.9)" fill="none" stroke-width="2"
                        stroke-linecap="round" stroke-linejoin="round" />
                </svg>
            </div>
        </div>
        <!-- 日历主体 -->
        <table class="diy-calendar-table">
            <!-- 星期栏 -->
            <thead>
                <tr class="table-header-row">
                    <th v-for="day in dayNameList" :key="day.chineseShortName" class="table-header">
                        {{ day.chineseFullName }}
                    </th>
                </tr>
            </thead>
            <!-- 日期部分 -->
            <tbody>
                <tr class="table-body-row" v-for="(row, index) in calendarData" :key="index">
                    <td v-for="col in row" class="table-data" :data-date="col.dateNumber"
                        :key="`${col.dateObj.getMonth()}-${col.dateNumber}`">
                        <div class="td-content-box">
                            <div class="content-border" :class="{ selected: isSelectedDate(col) }"
                                @click="checkoutTargetDate(col)">
                                <div class="date-number" :class="{ current: isCurrentMonth(col) }">
                                    {{ col.dateNumber }}
                                </div>
                                <!--<div class="the-tradition-chinese-calendar">
                    {{ col.dateObj }}
                  </div>-->
                            </div>
                        </div>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</template>

<script setup>
import { reactive, ref, computed, watch } from "vue";
import dayjs from "dayjs"
const props = defineProps({
    modelValue: Date,
});

const emits = defineEmits(["update:modelValue"]);

/**
 * 最小年份
 */
const MIN_YEAR = 1900;
/**
 * 最大年份
 */
const MAX_YEAR = 9999;

/**
 * 目标日期
 * @type {Ref<Date>}
 */
const targetDate = ref(props.modelValue);

/**
 * 有关月度的名称列表
 */
const monthNameList = {
    chineseFullName: [
        "一月",
        "二月",
        "三月",
        "四月",
        "五月",
        "六月",
        "七月",
        "八月",
        "九月",
        "十月",
        "十一月",
        "十二月",
    ],
    fullName: [
        "January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December",
    ],
    mmm: [
        "Jan",
        "Feb",
        "Mar",
        "Apr",
        "May",
        "Jun",
        "Jul",
        "Aug",
        "Sep",
        "Oct",
        "Nov",
        "Dec",
    ],
};
/**
 * 有关周几的名称列表
 */
const dayNameList = [
    {
        chineseFullName: "周日",
        chineseShortName: "日",
        fullName: "Sunday",
        shortName: "Sun",
        dayNumber: 0,
    },
    {
        chineseFullName: "周一",
        chineseShortName: "一",
        fullName: "Monday",
        shortName: "Mon",
        dayNumber: 1,
    },
    {
        chineseFullName: "周二",
        chineseShortName: "二",
        fullName: "Tuesday",
        shortName: "Tue",
        dayNumber: 2,
    },
    {
        chineseFullName: "周三",
        chineseShortName: "三",
        fullName: "Wednesday",
        shortName: "Wed",
        dayNumber: 3,
    },
    {
        chineseFullName: "周四",
        chineseShortName: "四",
        fullName: "Thursday",
        shortName: "Thu",
        dayNumber: 4,
    },
    {
        chineseFullName: "周五",
        chineseShortName: "五",
        fullName: "Friday",
        shortName: "Fri",
        dayNumber: 5,
    },
    {
        chineseFullName: "周六",
        chineseShortName: "六",
        fullName: "Saturday",
        shortName: "Sat",
        dayNumber: 6,
    },
];
/**
 * 今日
 */
const today = new Date();

/**
 * 日历的各项属性
 */
const calendarProps = reactive({
    target: {
        year: null,
        month: null,
        date: null,
        day: null,
        monthShortName: null,
        monthFullName: null,
        monthChineseFullName: null,
        firstDay: null,
        firstDayIndex: null,
        totalDays: null,
    },
    previous: {
        totalDays: null,
    },
});

/**
 * 用于展现的日历数据
 */
const calendarData = ref([]);

initCalendar();

/**
 * 初始化日历数据
 */
function initCalendar() {
    setCalendarProps();
    setCalendarData();
}

/**
 * 设置日历的各个属性，比如当前年月日，本月一共多少天，上个月一共多少天等等
 */
function setCalendarProps() {
    if (!targetDate.value) {
        targetDate.value = today;
    }
    // 获取目标日期的年月日星期几数据
    calendarProps.target.year = targetDate.value.getFullYear();
    calendarProps.target.month = targetDate.value.getMonth();
    calendarProps.target.date = targetDate.value.getDate();
    calendarProps.target.day = targetDate.value.getDay();

    if (
        calendarProps.target.year < MIN_YEAR ||
        calendarProps.target.year > MAX_YEAR
    ) {
        console.error("无效的年份，请检查传入的数据是否是正常");
        return;
    }

    // 获取到目标日期的月份【中文】名称
    let dateString;
    dateString = targetDate.value.toString().split(" ");
    calendarProps.target.monthShortName = dateString[1];
    calendarProps.target.monthFullName =
        monthNameList.fullName[calendarProps.target.month];
    calendarProps.target.monthChineseFullName =
        monthNameList.chineseFullName[calendarProps.target.month];
    // 获取目标月份的第一天是星期几，和在星期几中的索引值
    const targetMonthFirstDay = new Date(
        calendarProps.target.year,
        calendarProps.target.month,
        1
    );
    calendarProps.target.firstDay = targetMonthFirstDay.getDay();
    calendarProps.target.firstDayIndex = dayNameList.findIndex(
        (day) => day.dayNumber === calendarProps.target.firstDay
    );

    // 获取目标月份总共多少天
    const targetMonthLastDay = new Date(
        calendarProps.target.year,
        calendarProps.target.month + 1,
        0
    );
    calendarProps.target.totalDays = targetMonthLastDay.getDate();

    // 获取目标月份的上个月总共多少天
    const previousMonth = new Date(
        calendarProps.target.year,
        calendarProps.target.month,
        0
    );
    calendarProps.previous.totalDays = previousMonth.getDate();

    console.log('calendarProps:', calendarProps);
}

/**
 * 生成日历的数据
 */
function setCalendarData() {
    let i;
    let date = 1;
    const originData = [];
    const firstRow = [];
    // 设置第一行数据
    for (i = 0; i <= 6; i++) {
        // 设置目标月份之前月份的日期数据
        if (i < calendarProps.target.firstDayIndex) {
            const previousDate =
                calendarProps.previous.totalDays -
                calendarProps.target.firstDayIndex +
                (i + 1);
            firstRow.push({
                dateObj: new Date(
                    calendarProps.target.year,
                    calendarProps.target.month - 1,
                    previousDate
                ),
                dateNumber: previousDate,
                dateType: "previous",
            });
        } else {
            // 设置目标月份当月的日期数据
            firstRow.push({
                dateObj: new Date(
                    calendarProps.target.year,
                    calendarProps.target.month,
                    date
                ),
                dateNumber: date,
                dateType: "current",
            });
            date++;
        }
    }
    originData.push(firstRow);
    // 设置后面五行的数据
    for (let j = 0; j <= 4; j++) {
        const rowData = [];
        for (let k = 0; k <= 6; k++) {
            // 设置目标月份剩下的日期数据
            if (date <= calendarProps.target.totalDays) {
                rowData.push({
                    dateObj: new Date(
                        calendarProps.target.year,
                        calendarProps.target.month,
                        date
                    ),
                    dateNumber: date,
                    dateType: "current",
                });
            } else {
                // 设置目标月份下个月的日期数据
                const nextDate = date - calendarProps.target.totalDays;
                rowData.push({
                    dateObj: new Date(
                        calendarProps.target.year,
                        calendarProps.target.month + 1,
                        nextDate
                    ),
                    dateNumber: nextDate,
                    dateType: "next",
                });
            }
            date++;
        }
        originData.push(rowData);
    }
    calendarData.value = originData;
}

/**
 * 是否是被选中的日期
 * @param col 日期数据
 */
function isSelectedDate(col) {
    const colDateObj = col.dateObj;
    const colYear = colDateObj.getFullYear();
    const colMonth = colDateObj.getMonth();
    const colDate = colDateObj.getDate();

    const targetDateYear = targetDate.value.getFullYear();
    const targetDateMonth = targetDate.value.getMonth();
    const targetDateDate = targetDate.value.getDate();

    if (
        colYear === targetDateYear &&
        colMonth === targetDateMonth &&
        colDate === targetDateDate
    ) {
        return true;
    } else {
        return false;
    }
}

/**
 * 是否是当前月份
 * @param col 日期数据
 */
function isCurrentMonth(col) {
    if (col.dateType !== "current") {
        return false;
    } else {
        return true;
    }
}

/**
 * 切换目标日期
 * @param col 日期数据
 */
function checkoutTargetDate(col) {
    const currentDate = col.dateObj;
    const oldDate = targetDate.value;
    // 如果本次点击的日期是当前选中的日期，则停止执行
    if (currentDate.getTime() === oldDate.getTime()) {
        return;
    }
    if (col.dateType === "current") {
        targetDate.value = col.dateObj;
        setCalendarProps();
    } else {
        targetDate.value = col.dateObj;
        initCalendar();
    }
}

/**
 * 跳转月份
 * @param flag 跳转数字标识，+1，就是增加一个月，-1就是减少一个月
 */
function jumpMonth(flag) {
    let targetMonthNumber = calendarProps.target.month;
    let targetYear = calendarProps.target.year;
    targetDate.value = calendarProps.target.date;
    targetMonthNumber += flag;
    console.log('targetMonthNumber', calendarProps.target.month, targetMonthNumber);
    if (targetMonthNumber > 11) {
        targetYear += 1;
        targetMonthNumber = 0;
    } else if (targetMonthNumber < 0) {
        targetYear -= 1;
        targetMonthNumber = 11;
    }
    targetDate.value = new Date(targetYear, targetMonthNumber, targetDate.value);
    initCalendar();
}

const targetDateFormat = computed(() => {
    const monthNumber = targetDate.value.getMonth() + 1
    let monthString = "";

    if (monthNumber > 9) {
        monthString = monthNumber + '';
    } else {
        monthString = '0' + monthNumber;
    }
    return `${targetDate.value.getFullYear()}.${monthString}`;
});

watch(targetDate, (newVal) => {
    emits("update:modelValue", newVal);
});
</script>

<style scoped lang="scss">
.diy-calendar-wrapper {
    width: auto;
    height: 100%;

    .calendar-header {
        height: 54px;
        padding: 13px 20px;
        margin-bottom: 15px;
        display: flex;
        justify-content: space-between;
        user-select: none;

        .left-arrow,
        .right-arrow {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            background-color: rgba(215, 221, 228, 0.2);
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
            border: 1px solid rgba(95, 147, 238, 0.5);
            transition: all 0.2s;
            overflow: hidden;

            &:hover {
                border: 1px solid rgba(8, 94, 243, 0.9);
            }
        }

        .center-title {
            display: flex;
            justify-content: center;
            align-items: center;
            font-family: Magneto;
            font-size: 30px;
            font-weight: bold;
        }
    }

    .diy-calendar-table {
        width: 100%;
        user-select: none;
        border-collapse: collapse;

        .table-header-row {
            height: 32px;
            background-color: rgba(95, 147, 238, 0.06);

            .table-header {
                font-size: 16px;
                text-align: center;
                font-family: "Lucida Handwriting";
                font-weight: bold;
            }
        }

        .table-body-row {
            height: 75px;

            .table-data {
                text-align: center;

                .td-content-box {
                    width: 100%;
                    height: 100%;
                    display: flex;
                    justify-content: center;
                    align-items: center;

                    .content-border {
                        position: relative;
                        width: 60px;
                        height: 60px;
                        border-radius: 50%;
                        cursor: pointer;
                        transition: all ease 0.3s;

                        .table-badge {
                            width: 14px;
                            height: 14px;
                            border-radius: 50%;
                            position: absolute;
                            right: 3px;
                            top: 3px;
                            background-color: rgba(20, 167, 59, 0.5);
                            color: #ffffff;
                            font-size: 10px;
                            transition: all ease 0.3s;

                            &.current {
                                background-color: #14a73b;
                                font-weight: normal;
                            }
                        }

                        .date-number {
                            width: 100%;
                            position: absolute;
                            left: 0;
                            text-align: center;
                            top: 20px;
                            font-size: 18px;
                            line-height: 20px;
                            transition: all ease 0.3s;
                            font-family: Magneto;
                            font-weight: normal;
                            // color: rgba(42, 63, 103, 0.48);
                            color: #666;

                            &.current {
                                // color: #435069;
                                color: #cdd2d8;

                                font-weight: bold;
                            }
                        }

                        .the-tradition-chinese-calendar {
                            width: 40px;
                            position: absolute;
                            left: 10px;
                            top: 34px;
                            font-size: 10px;
                            transition: all ease 0.2s;
                        }

                        &.selected {
                            //background: #023f99;
                            background: radial-gradient(#2B6CFF , #0062fb );
                            border-radius: 50%;

                            .table-badge {
                                background: #ffffff;
                                color: #023f99;
                            }

                            .date-number {
                                color: #ffffff;
                            }

                            .the-tradition-chinese-calendar {
                                color: #ffffff;
                            }

                            /* &::before,
                            &::after {
                                content: "";
                                position: absolute;
                                width: 80px;
                                height: 80px;
                                border: 3px solid rgba(2, 63, 153, 0.5);
                                border-radius: 50%;
                                inset: -10px;
                            }

                            &::before {
                                // animation: pathRotate1 4s linear infinite;
                            }

                            &::after {
                                animation: pathRotate2 4s linear infinite;
                            } */
                        }
                    }
                }
            }
        }
    }
}

@keyframes pathRotate1 {

    0%,
    100% {
        clip-path: inset(0 0 95% 0);
    }

    25% {
        clip-path: inset(0 0 0 95%);
    }

    50% {
        clip-path: inset(95% 0 0 0);
    }

    75% {
        clip-path: inset(0 95% 0 0);
    }
}

@keyframes pathRotate2 {

    0%,
    100% {
        clip-path: inset(95% 0 0 0);
    }

    25% {
        clip-path: inset(0 95% 0 0);
    }

    50% {
        clip-path: inset(0 0 95% 0);
    }

    75% {
        clip-path: inset(0 0 0 95%);
    }
}
</style>