import React from 'react';
import './Calendar.scss';
import {jdnDate} from '@common/gregorian';
import {jdnLongCount} from '@common/longCount';
import {MonthBasedCalendar} from '@common/ui/MonthBasedCalendar';
import {
    formatLordOfNight,
    HaabDay,
    haabExtJDN,
    HaabMonth,
    haabMonthDays,
    haabNames,
    HaabYear,
    jdnHaabExt,
    jdnLordOfNight,
} from '@common/mayan';

type MonthProps = {
    year: HaabYear;
    month: HaabMonth;
};

type DateProps = MonthProps & {
    day: HaabDay;
};

function NormalDay({year, month, day, todayJDN}: DateProps & { todayJDN: number }): JSX.Element {
    const jdn = haabExtJDN({year, month, day});
    return <div className={`Day ${jdn === todayJDN ? 'Day-today' : ''}`}>
        <div className="Day-name">{day}</div>
        <div className="DayDetail-lc">{jdnLongCount(jdn)?.join('.')}</div>
        <div className="Day-lordOfNight">{formatLordOfNight(jdnLordOfNight(jdn))}</div>
        <div className="DayDetail-gregorian">{jdnDate(jdn).toDateString()}</div>
    </div>;
}

function Month({year, month, todayJDN}: MonthProps & { todayJDN: number }): JSX.Element {
    return <div className="Month">
        <div className="Month-days">{
            Array.from(Array(haabMonthDays(month)).keys()).map(i => <div key={i} className="DayOuter NormalDay">
                <NormalDay year={year} month={month} day={i + 1 as HaabDay} todayJDN={todayJDN}/>
            </div>)
        }</div>
    </div>;
}

export class Calendar extends MonthBasedCalendar<HaabYear, HaabMonth> {
    override parseYear(year: string): HaabYear {
        return +year;
    }

    override parseMonth(month: string): HaabMonth {
        return +month as HaabMonth;
    }

    override yearToString(year: HaabYear): string {
        return year.toString();
    }

    override monthToString(month: HaabMonth): string {
        return month.toString();
    }

    private goToNormalized(year: number, month: number) {
        while (month < 1) {
            --year;
            month += 19;
        }

        while (month > 19) {
            ++year;
            month -= 19;
        }

        this.goTo(year, month as HaabMonth);
    }

    override prevYear = () => {
        this.goToNormalized(this.props.year - 1, this.props.month);
    };

    override prevMonth = () => {
        this.goToNormalized(this.props.year, this.props.month - 1);
    };

    override nextYear = () => {
        this.goToNormalized(this.props.year + 1, this.props.month);
    };

    override nextMonth = () => {
        this.goToNormalized(this.props.year, this.props.month + 1);
    };

    override isValidYear(year: string): boolean {
        return /^-?\d+/.test(year);
    }

    override jdnLookup(jdn: number): { year: HaabYear; month: HaabMonth } {
        return jdnHaabExt(jdn);
    }

    override monthName(year: HaabYear, month: HaabMonth): string {
        return `${haabNames[month]} ${year}`;
    }

    override renderMonthOptions(): JSX.Element[] {
        return Array.from(Array(19).keys()).map(i => {
            const month = i + 1 as HaabMonth;
            return <option key={i} value={month}>{haabNames[month]}</option>;
        });
    }

    override renderBody(): JSX.Element {
        return <Month year={this.props.year} month={this.props.month} todayJDN={this.props.todayJDN}/>;
    }
}
