const MONTHS = [ "Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre", ];

class Holiday {
	constructor(day, month, year) {
		this.day = day;
		this.month = month;
		this.year = year;
	}
	match(day, month, year) {
		if(this.year !== undefined && this.year != year) {
			return false;
		}
		return this.day == day && this.month == month;
	}
}
const holidays = [
    new Holiday(1, 1),
	new Holiday(6, 1),
	new Holiday(25, 4),
	new Holiday(1, 5),
	new Holiday(2, 6),
	new Holiday(15, 8),
	new Holiday(1, 11),
	new Holiday(8, 12),
	new Holiday(25, 12),
	new Holiday(26, 12),
	// pasquette (le pasque non servono perché domenica)
	new Holiday(21, 4, 2025),
	new Holiday(6, 4, 2026),
	new Holiday(29, 3, 2027),
	new Holiday(17, 4, 2028),
	new Holiday(2, 4, 2029),
]
function isHoliday(holidays, day, month, year) {
	if(this.day === NaN) { return false; }
	return holidays.some((h) => h.match(day, month, year));
}

class Calendar {
	constructor({ elem, year, month }) {
		this.elem = elem;
		this.year = year;
		this.month = month;
		this.date = new Date(year, month - 1);
		this._insertCalendar();
	}
	_addRow(table) {
		let row = document.createElement("tr");
		table.append(row);
	}
	_addCell(row) {
		let cell = document.createElement("td");
		row.append(cell);
	}
	_getMonthString() {
		return MONTHS[this.date.getMonth()];
	}
	_constructTable() {
		let table = document.createElement("table");
		table.innerHTML =
			'<table><thead><tr><th></th></tr><tr><th>L</th><th>M</th><th>Me</th><th>G</th><th>V</th><th>S</th><th class="holyday">D</th></tr></thead><tbody></tbody></table>';
		table.rows[0].cells[0].colSpan = 7;
		table.rows[0].cells[0].innerHTML = this._getMonthString();
		for (let row = 2; row < 8; row++) {
			this._addRow(table.tBodies[0]);
			table.rows[row].dataset.week = "" + (row - 1);
			for (let cell = 0; cell < 7; cell++) {
				this._addCell(table.rows[table.rows.length - 1]);
				if (cell === 6) {
					table.rows[row].cells[cell].dataset.weekDay = "" + 0;
				} else table.rows[row].cells[cell].dataset.weekDay = "" + (cell + 1);
			}
		}
		return table;
	}
	_constructCalendar() {
		let table = this._constructTable();
		outer: while (this.date.getMonth() < this.month) {
			let d = 0;
			for (let row = 2; row < 8; row++) {
				for (let cell = 0; cell < 7; cell++) {
					this.date.setDate(this.date.getDate() + d);
					if (this.date.getDay() != table.rows[2].cells[cell].dataset.weekDay)
						continue;
					if (
						this.date.getMonth() > this.month - 1 ||
						(this.date.getMonth() == 0 && this.month == 12)
					) {
						while (table.rows[table.rows.length - 1].cells[0].innerHTML === "")
							table.tBodies[0].lastElementChild.remove();
						break outer;
					}
					table.rows[row].cells[cell].innerHTML = "" + this.date.getDate();
					d = 1;
				}
			}
		}
		return table;
	}
	_insertCalendar() {
		let calendar = this._constructCalendar();
		for (let week = 0; week < calendar.rows.length; week++) {
			for (let day = 0; day < calendar.rows[week].cells.length; day++) {
				let currentDay = calendar.rows[week].cells[day];
                if(currentDay.textContent !== "") {
                    currentDay.classList.add("day")
                }
				if (currentDay.dataset.weekDay == 0 ||
					  isHoliday(holidays, parseInt(currentDay.textContent, 10), this.month, this.year)
					 ) {
					currentDay.classList.add("holyday");
                }
			}
		}
		this.elem.append(calendar);
	}
}

function createYear(year, first) {
    let container = document.createElement("section")
    container.classList.add("year")
    document.body.insertBefore(container, document.body.lastElementChild);
    let h1 = document.createElement("h1");
    h1.innerHTML = year;
    container.append(h1);

    let yearCalendarcurrentYear = document.createElement("div");
    yearCalendarcurrentYear.classList.add("yearCalendar");
    container.append(yearCalendarcurrentYear);

    let monthscurrentYear = [];
    for(let i=0; i<12; i++) {
        let month = { 
                name: MONTHS[i],
                index: i+1,
                node: createDiv(),
                calendar: createMonthCalendar
            }
        yearCalendarcurrentYear.append(month.calendar(year));
    }
}

function createDiv() {
	return document.createElement("div");
}

function createMonthCalendar(year) {
	let calendar = new Calendar({
		elem: this.node,
		year: year,
		month: this.index
	});
	this.node.classList.add("month");
	this.node.classList.add("month-num-" + this.index);
    this.node.classList.add("month-length-" + calendar.elem.querySelectorAll(':scope td.day').length);
	return this.node;
}

createYear((new Date()).getFullYear() + 1, true);
for(let i=2; i<10;i++) {
    createYear((new Date()).getFullYear() + i, false);
}
