<?php
/**
 * Script Title: Calendar
 *
 * Copyright (c) 2024 [Djulia]
 *
 * This script is free to use, modify, and distribute under the following license:
 * 
 * 1. Attribution: You must attribute the work to the original author.
 * 2. Commercial Use: You may use this code in commercial projects.
 * 3. Modifications: You may modify the code, but you must clearly indicate any changes made.
 * 4. Distribution: If you distribute the code or its modifications, you must include this license.
 * 
 * No warranty is provided, and the author cannot be held responsible for any damages resulting from the use of this code.
 *
 * ## Requirements
 * - PHP 8.2 or higher
 *
 * For more information or any questions, please contact via the Interactive Tools forum: 
 * https://www.interactivetools.com/forum/
 */

// Set the default language for the calendar (e.g., 'en' for English, 'fr' for French)
$lang = 'en';

// Set the first day of the week (e.g., 'monday' or 'sunday')
$weekStart = 'sunday';

// Define working hours as variables
$workingStartTime = '06:00';
$workingEndTime   = '21:00';


/**
 * Retrieves and validates calendar parameters from the GET request.
 * Defaults to the current month, year, week, and day if parameters are not set.
 */
function getCalendarParams() {
    // Define default parameters
    $defaults = [
        'view'  => 'week',
        'year'  => date('Y'),
        'month' => date('m'),
        'week'  => date('W'),
        'day'   => date('d')
    ];

    // Retrieve GET parameter values, using default values if not set
    $view  = isset($_GET['view']) ? $_GET['view'] : $defaults['view'];
    $year  = isset($_GET['year']) ? intval($_GET['year']) : $defaults['year'];
    $month = isset($_GET['month']) ? intval($_GET['month']) : $defaults['month'];
    $week  = isset($_GET['week']) ? intval($_GET['week']) : $defaults['week'];
    $day   = isset($_GET['day']) ? intval($_GET['day']) : $defaults['day'];

    // List of allowed views
    $allowed_views = ['month', 'week', 'day', 'year'];

    // Parameter validation
    $view = in_array($view, $allowed_views) ? $view : $defaults['view'];
    $year = ($year >= 1970 && $year <= date('Y') + 5) ? $year : $defaults['year'];
    $month = ($month >= 1 && $month <= 12) ? $month : $defaults['month'];
    $week = ($week >= 1 && $week <= 53) ? $week : $defaults['week'];
    $day = ($day >= 1 && $day <= 31) ? $day : $defaults['day'];

    // Return validated parameters as an array
    return [
        'view'  => $view,
        'year'  => $year,
        'month' => $month,
        'week'  => $week,
        'day'   => $day
    ];
}


// Translation arrays for days and months...
$translations = [
    'en' => [
        'days' => [
            'short' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
            'long' => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
        ],
        'months' => [
            'short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
            'long' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
        ],
        'navigation' => [
            'previous_day' => 'Previous day',
            'today' => 'Today',
            'next_day' => 'Next day',
            'previous_week' => 'Previous week',
            'this_week' => 'This week',
            'next_week' => 'Next week',
            'previous_month' => 'Previous month',
            'this_month' => 'This month',
            'next_month' => 'Next month',
            'month' => 'Month',
            'week' => 'Week',
            'day' => 'Day',
            'year' => 'Year',
			'previous_year' => 'Previous year',
			'this_year' => 'This year',
			'next_year' => 'Next year'
        ],
        'labels' => [
            'hour' => 'Hour',
            'day' => 'Day',
            'week' => 'Week',
            'month' => 'Month',
            'event' => 'Events'
        ]
    ],
    'fr' => [
        'days' => [
            'short' => ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'],
            'long' => ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi']
        ],
        'months' => [
            'short' => ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Aoû', 'Sep', 'Oct', 'Nov', 'Déc'],
            'long' => ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']
        ],
        'navigation' => [
            'previous_day' => 'Jour précédent',
            'today' => 'Aujourd\'hui',
            'next_day' => 'Jour suivant',
            'previous_week' => 'Semaine précédente',
            'this_week' => 'Cette semaine',
            'next_week' => 'Semaine suivante',
            'previous_month' => 'Mois précédent',
            'this_month' => 'Ce mois-ci',
            'next_month' => 'Mois suivant',
            'month' => 'Mois',
            'week' => 'Semaine',
            'day' => 'Jour',
		    'year' => 'Année',
			'previous_year' => 'Année précédente',
			'this_year' => 'Cette année',
			'next_year' => 'Année suivante'
		],
        'labels' => [
            'hour' => 'Heures',
            'day' => 'Jour',
            'week' => 'Semaine',
            'month' => 'Mois',
            'event' => 'Événements'
        ]
    ],
    'es' => [
        'days' => [
            'short' => ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'],
            'long' => ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado']
        ],
        'months' => [
            'short' => ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
            'long' => ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']
        ],
        'navigation' => [
            'previous_day' => 'Día anterior',
            'today' => 'Hoy',
            'next_day' => 'Día siguiente',
            'previous_week' => 'Semana anterior',
            'this_week' => 'Esta semana',
            'next_week' => 'Semana siguiente',
            'previous_month' => 'Mes anterior',
            'this_month' => 'Este mes',
            'next_month' => 'Mes siguiente',
            'month' => 'Mes',
            'week' => 'Semana',
            'day' => 'Día',
			'year' => 'Año',
			'previous_year' => 'Año anterior',
			'this_year' => 'Este año',
			'next_year' => 'Año siguiente'
		],
        'labels' => [
            'hour' => 'Hora',
            'day' => 'Día',
            'week' => 'Semana',
            'month' => 'Mes',
            'event' => 'Eventos'
        ]
    ]
];


// VIEW SELECTOR
function renderViewSwitcher(
    int $month,
    int $year,
    int $week,
    string $currentView,
    string $lang = 'en',
    array $translations = []
): void {
    // Check if the language exists in the translations
    $translations[$lang] = $translations[$lang] ?? $translations['en'];

    // Retrieve the translated navigation terms
    $navTexts = $translations[$lang]['navigation'];

    echo "<div class='view-switcher'>";
    // echo "<a href='?year={$year}&view=year'" . ($currentView === 'year' ? " class='active'" : "") . ">{$navTexts['year']}</a> | ";
    echo "<a href='?month={$month}&year={$year}&view=month'" . ($currentView === 'month' ? " class='active'" : "") . ">{$navTexts['month']}</a> | ";
    echo "<a href='?year={$year}&week={$week}&view=week'" . ($currentView === 'week' ? " class='active'" : "") . ">{$navTexts['week']}</a> | ";
    echo "<a href='?month={$month}&year={$year}&view=day'" . ($currentView === 'day' ? " class='active'" : "") . ">{$navTexts['day']}</a>";
    echo "</div>";
}


// MONTH VIEW
function renderMonthCalendar(
    int $month,
    int $year,
    array $events,
    string $weekStart = 'monday',
    string $lang = 'en',
    array $translations = []
): void {
    // Retrieve translations based on the language or use the default language
    $translations[$lang] = $translations[$lang] ?? $translations['en'];
    $monthName = $translations[$lang]['months']['long'][$month - 1];

    // Display the month name and year
    echo "<h2>$monthName $year</h2>";

    // Get the days of the week in the correct language and rearrange if necessary
    $daysOfWeek = $weekStart === 'sunday' 
        ? $translations[$lang]['days']['short'] 
        : array_merge(array_slice($translations[$lang]['days']['short'], 1), array_slice($translations[$lang]['days']['short'], 0, 1));

    $numDays = cal_days_in_month(CAL_GREGORIAN, $month, $year);
    $firstDayOfMonth = new DateTimeImmutable("$year-$month-01");
    $firstDayOfWeek = (int) $firstDayOfMonth->format('N'); // 1 (Monday) - 7 (Sunday)
    
    // Calculate the offset based on the start day of the week
    $startOffset = $weekStart === 'sunday' ? $firstDayOfWeek % 7 : $firstDayOfWeek - 1;
    
    // Calculate dates for the previous and next months
    $prevMonth = $month - 1 < 1 ? 12 : $month - 1;
    $prevYear = $month - 1 < 1 ? $year - 1 : $year;
    $prevMonthDays = cal_days_in_month(CAL_GREGORIAN, $prevMonth, $prevYear);

    $nextMonth = $month + 1 > 12 ? 1 : $month + 1;
    $nextYear = $month + 1 > 12 ? $year + 1 : $year;

    $today = new DateTimeImmutable();

    echo "<table class='calendar-month'>";
    echo "<thead><tr>";
    foreach ($daysOfWeek as $day) {
        echo "<th>$day</th>";
    }
    echo "</tr></thead>";

    echo "<tbody><tr>";

    // Display the last days of the previous month
    for ($i = $startOffset - 1; $i >= 0; $i--) {
        $prevDay = $prevMonthDays - $i;
        renderMonthDayCell($prevYear, $prevMonth, $prevDay, $events, 'prev-month', false);
    }

    // Display the days of the current month
    for ($day = 1; $day <= $numDays; $day++) {
        $currentDate = new DateTimeImmutable("$year-$month-$day");
        $isToday = $currentDate->format('Y-m-d') === $today->format('Y-m-d');
        $class = $isToday ? 'today' : '';
        renderMonthDayCell($year, $month, $day, $events, $class, false);

        // Start a new row if the end of the week is reached
        if (($day + $startOffset) % 7 === 0) {
            echo "</tr><tr>";
        }
    }

    // Display the first days of the next month
    $remainingCells = (7 - (($numDays + $startOffset) % 7)) % 7;
    for ($i = 1; $i <= $remainingCells; $i++) {
        renderMonthDayCell($nextYear, $nextMonth, $i, $events, 'next-month', false);
    }

    echo "</tr></tbody></table>";
}


// Utility function to render a day of the calendar
function renderMonthDayCell(
    int $year, 
    int $month, 
    int $day, 
    array $events, 
    string $class = '', 
    bool $isYearView = false, 
    string $eventCategory = ''
): void {
    $currentDate = new DateTimeImmutable("$year-$month-$day");

    // Add a link to the day cell
    $dayLink = "?year={$year}&month={$month}&day={$day}&view=day";

    echo "<td class='$class'><div class='day'>";
    echo "<a href='$dayLink' class='day-number'>$day</a>";  // Wrap the day number in a link

	if ($isYearView) {

		// Displays events for this day
		echo "<div class='event-container'>";
		foreach ($events as $event) {
			$eventStart = new DateTimeImmutable($event['start_date']);
			$eventEnd = new DateTimeImmutable($event['end_date']);

			// Checks if the event concerns this date
			if ($eventStart->format('Y-m-d') === $currentDate->format('Y-m-d') || 
				$eventEnd->format('Y-m-d') === $currentDate->format('Y-m-d') || 
				($eventStart <= $currentDate && $eventEnd >= $currentDate)) {

				// Generates a tooltip with description and location
				$tooltip = "Description: {$event['description']}<br>Location: {$event['location']}";
				$category = $event['category'] ?? $eventCategory; 

				// Year view
				echo "<a href='{$event['permalink']}' class='tooltip'>";
				echo "<div class='event {$category}'>";
				echo "<span class='tooltiptext'>$tooltip</span>";
				echo "</div>";
				echo "</a>";
			}
		}
		echo "</div>";

	} else { // Monthly view

		// Displays events for this day
		foreach ($events as $event) {
			$eventStart = new DateTimeImmutable($event['start_date']);
			$eventEnd = new DateTimeImmutable($event['end_date']);

			// Checks if the event concerns this date
			if ($eventStart->format('Y-m-d') === $currentDate->format('Y-m-d') || 
				$eventEnd->format('Y-m-d') === $currentDate->format('Y-m-d') || 
				($eventStart <= $currentDate && $eventEnd >= $currentDate)) {

				// Generates a tooltip with description and location
				$tooltip = "Description: {$event['description']}<br>Location: {$event['location']}";
				$category = $event['category'] ?? $eventCategory; 

				// Monthly view
				echo "<div class='event {$category}'>";
				echo "{$event['title']}";
				// echo "<span class='tooltiptext'>$tooltip</span>";
				echo "</div>";
			}
		}
	}

    echo "</div></td>";
}

// MONTH NAV
function renderMonthNavigation(
    int $month,
    int $year,
    string $lang = 'en',
    array $translations = []
): void {
    // Check if the language exists in the translations
    $translations[$lang] = $translations[$lang] ?? $translations['en'];

    // Retrieve the translated navigation terms
    $navTexts = $translations[$lang]['navigation'];

    // Create a DateTimeImmutable object for the current month
    $currentDate = new DateTimeImmutable("$year-$month-01");

    // Calculate the previous month and the next month
    $prevMonthDate = $currentDate->modify('-1 month');
    $nextMonthDate = $currentDate->modify('+1 month');

    // Generate the navigation links
    echo "<div class='calendar-navigation'>";
    echo "<a href='?month={$prevMonthDate->format('m')}&year={$prevMonthDate->format('Y')}'>&lt; {$navTexts['previous_month']}</a>";
    echo " | <a href='?month=" . date('m') . "&year=" . date('Y') . "'>{$navTexts['this_month']}</a> | ";
    echo "<a href='?month={$nextMonthDate->format('m')}&year={$nextMonthDate->format('Y')}'>{$navTexts['next_month']} &gt;</a>";
    echo "</div>";
}


// WEEK VIEW
function renderWeekView(
    int $month,
    int $year,
    int $week,
    array $events,
    string $weekStart = 'monday',
    string $lang = 'en',
    array $translations = [],
    string $workingStartTime = '08:00', 
    string $workingEndTime = '18:30'
): void {
    $translations[$lang] = $translations[$lang] ?? $translations['en'];

    $navTexts = $translations[$lang]['labels'];
    $daysOfWeek = $translations[$lang]['days']['short'];
    $monthsShort = $translations[$lang]['months']['short'];
    $monthsLong = $translations[$lang]['months']['long']; // Added long months

    if ($weekStart === 'monday') {
        $firstDay = array_shift($daysOfWeek);
        array_push($daysOfWeek, $firstDay);
    }

    $firstDayOfYear = new DateTimeImmutable("$year-01-01");
    $firstDayOfWeek = $firstDayOfYear->modify("+".($week - 1)." weeks");

    $firstDayOfWeek = ($weekStart === 'sunday')
        ? $firstDayOfWeek->modify('last sunday')
        : $firstDayOfWeek->modify('monday this week');

    $monthName = $monthsLong[$firstDayOfWeek->format('n') - 1]; // Use long format

	echo "<h2>$monthName $year - {$navTexts['week']} $week</h2>";
    echo "<table class='calendar-week'>";
    echo "<thead><tr><th>{$navTexts['hour']}</th>";

    foreach ($daysOfWeek as $dayOffset => $day) {
        $currentDay = $firstDayOfWeek->modify("+$dayOffset days");
        $dayNumber = $currentDay->format('d');

        // Add a link for each day that redirects to the daily view
        $dayLink = "?year={$currentDay->format('Y')}&month={$currentDay->format('m')}&day={$currentDay->format('d')}&view=day";
        echo "<th><a href='$dayLink'>$day $dayNumber</a></th>";
    }
    echo "</tr></thead>";
    echo "<tbody>";

    $workingStart = DateTimeImmutable::createFromFormat('H:i', $workingStartTime);
    $workingEnd = DateTimeImmutable::createFromFormat('H:i', $workingEndTime);

    for ($hour = 6; $hour <= 22; $hour++) {
        $formattedHour = str_pad($hour, 2, '0', STR_PAD_LEFT) . ":00";
        $currentHour = DateTimeImmutable::createFromFormat('H:i', $formattedHour);

        echo "<tr><td class='hour'>$formattedHour</td>";

        for ($dayOffset = 0; $dayOffset < 7; $dayOffset++) {
            $currentDay = $firstDayOfWeek->modify("+$dayOffset days");
            $currentDate = $currentDay->format('Y-m-d');

            echo "<td class='week-day'>";

			foreach ($events as $event) {
				$eventStart = new DateTimeImmutable($event['start_date']);
				$eventEnd = new DateTimeImmutable($event['end_date']);

				// Condition to check if end_date needs to be corrected
				if ($eventEnd <= $eventStart) {
					// Add 1 hour to the start date for the end date
					$eventEnd = $eventStart->modify('+1 hour');
				}

				$isSameDay = ($eventStart->format('Y-m-d') === $eventEnd->format('Y-m-d'));
				
				// Create the event time display
				$eventTimeDisplay = '';
				if ($isSameDay) {
					// Single-day event
					$eventTimeDisplay = "<span class='event-time'>{$eventStart->format('H:i')} - {$eventEnd->format('H:i')}</span>";
				} else {
					// Multi-day event
					$startDay = $eventStart->format('d');
					$startMonth = $monthsShort[$eventStart->format('n') - 1];
					$startTime = $eventStart->format('H:i');
					
					$endDay = $eventEnd->format('d');
					$endMonth = $monthsShort[$eventEnd->format('n') - 1];
					$endTime = $eventEnd->format('H:i');
					
					$eventTimeDisplay = "<span class='event-time'>{$startDay} {$startMonth} {$startTime} - {$endDay} {$endMonth} {$endTime}</span>";
				}

				// Check if the event should be displayed
				if (
					($isSameDay && $currentDate === $eventStart->format('Y-m-d') && $hour >= (int)$eventStart->format('H') && $hour < (int)$eventEnd->format('H')) ||
					(!$isSameDay && (
						($currentDate === $eventStart->format('Y-m-d') && $hour >= (int)$eventStart->format('H')) ||
						($currentDate === $eventEnd->format('Y-m-d') && $hour < (int)$eventEnd->format('H')) ||
						($currentDate > $eventStart->format('Y-m-d') && $currentDate < $eventEnd->format('Y-m-d'))
					))
				) {
					renderWeekEvent($event, $eventTimeDisplay, $currentHour, $workingStart, $workingEnd);
				}
			}

            echo "</td>";
        }
        echo "</tr>";
    }

    echo "</tbody></table>";
}

// Renders a single event for the weekly calendar view, with title, link, and time display.
function renderWeekEvent(
	array $event, 
	string $eventTimeDisplay, 
	DateTimeImmutable $currentHour, 
	DateTimeImmutable $workingStart, 
	DateTimeImmutable $workingEnd,
	string $eventCategory = ''
): void {
    // Display only if the time is within working hours
    if ($currentHour >= $workingStart && $currentHour <= $workingEnd) {

		// Tooltip with description and location
		$tooltip = "Description: {$event['description']}<br>Location: {$event['location']}";
		$category = $event['category'] ?? $eventCategory; 

		echo "<div class='event {$category}'>";
        echo "{$event['title']}";
		// echo "<span class='tooltiptext'>$tooltip</span>"; // Add tooltip
		echo "<br>";
        echo $eventTimeDisplay;
        echo "</div>";
    }
}

// WEEK NAV
function renderWeekNavigation(
    int $currentYear,
    int $currentWeek,
    string $lang = 'en',
    array $translations = []
): void {
    // Check if the language exists in the translations
    $translations[$lang] = $translations[$lang] ?? $translations['en'];

    // Retrieve the translated navigation terms
    $navTexts = $translations[$lang]['navigation'];

    // DateTimeImmutable for the current week
    $currentDate = new DateTimeImmutable();
    $currentDate = $currentDate->setISODate($currentYear, $currentWeek);

    // Calculate the previous week
    $prevDate = $currentDate->modify('-1 week');
    $prevYear = $prevDate->format('o');  // 'o' returns the correct ISO year
    $prevWeek = $prevDate->format('W');  // ISO week number

    // Calculate the next week
    $nextDate = $currentDate->modify('+1 week');
    $nextYear = $nextDate->format('o');  // 'o' for the correct ISO year
    $nextWeek = $nextDate->format('W');  // ISO week number

    // Display the navigation with translated terms
    echo "<div class='calendar-navigation'>";
    echo "<a href='?year={$prevYear}&week={$prevWeek}&view=week'>&lt; {$navTexts['previous_week']}</a>";
    echo " | <a href='?year=" . date('o') . "&week=" . date('W') . "&view=week'>{$navTexts['this_week']}</a> | ";
    echo "<a href='?year={$nextYear}&week={$nextWeek}&view=week'>{$navTexts['next_week']} &gt;</a>";
    echo "</div>";
}


// DAY VIEW
function renderDayViewWithHours(
    int $month, 
    int $year, 
    int $day, 
    array $events, 
    string $lang = 'en', 
    array $translations = [], 
    string $workingStartTime = '08:00', 
    string $workingEndTime = '20:00',
	string $eventCategory = ''
): void {
    // Checking available translations
    $translations[$lang] = $translations[$lang] ?? $translations['en'];
    
    $navTexts = $translations[$lang]['labels'];
    $currentDate = new DateTimeImmutable("$year-$month-$day");
    $monthName = $translations[$lang]['months']['long'][$month - 1];
    $dayName = $translations[$lang]['days']['long'][$currentDate->format('w')];
    
    echo "<h2>$dayName, $day $monthName $year</h2>";
    echo "<table class='calendar-day'>";
    echo "<thead><tr><th>{$navTexts['hour']}</th><th>{$navTexts['event']}</th></tr></thead>";
    echo "<tbody>";
    
    // Preparing DateTime objects for working hours
    $workingStart = $currentDate->setTime(...explode(':', $workingStartTime));
    $workingEnd = $currentDate->setTime(...explode(':', $workingEndTime));
    
    // Loop to display working hours from 06:00 to 22:00
    for ($hour = 6; $hour < 23; $hour++) {
        $formattedHour = str_pad($hour, 2, '0', STR_PAD_LEFT) . ":00";
        echo "<tr>";
        echo "<td class='hour'>$formattedHour</td>";
        echo "<td class='day-event'>";

        // Loop through events
        foreach ($events as $event) {
            $eventStart = new DateTimeImmutable($event['start_date']);
            $eventEnd = new DateTimeImmutable($event['end_date']);

            // Condition to check if end_date needs to be corrected
            if ($eventEnd <= $eventStart) {
                // Add 1 hour to the start date for the end date
                $eventEnd = $eventStart->modify('+1 hour');
            }

            // Check if the event takes place on the current day
            $eventMatchesDay = $currentDate >= $eventStart->setTime(0, 0) && $currentDate <= $eventEnd->setTime(23, 59);
            if ($eventMatchesDay) {
                // Determine display start and end times within working hours
                $displayStart = max($eventStart, $workingStart);
                $displayEnd = min($eventEnd, $workingEnd);

                // Prepare time display based on the duration of the event
                $eventTimeDisplay = '';
                if ($eventStart->format('Y-m-d') === $eventEnd->format('Y-m-d')) {
                    // If the event is on a single day
                    $eventTimeDisplay = "<span class='event-time'>{$displayStart->format('H:i')} - {$displayEnd->format('H:i')}</span>";
                } else {
                    // If the event spans multiple days
                    $startDay = $eventStart->format('d');
                    $startMonth = $translations[$lang]['months']['short'][$eventStart->format('n') - 1]; // Short month name
                    $startTime = $eventStart->format('H:i');
                    
                    $endDay = $eventEnd->format('d');
                    $endMonth = $translations[$lang]['months']['short'][$eventEnd->format('n') - 1]; // Short month name
                    $endTime = $eventEnd->format('H:i');
                    
                    $eventTimeDisplay = "<span class='event-time'>{$startDay} {$startMonth} {$startTime} - {$endDay} {$endMonth} {$endTime}</span>";
                }

                // Display the event if it overlaps with working hours
                if ($hour >= (int)$displayStart->format('H') && $hour < (int)$displayEnd->format('H') + 1) {
                    $category = $event['category'] ?? $eventCategory;
					echo "<div class='event {$category}'>";
                    echo "{$event['title']}<br>";
                    echo $eventTimeDisplay; // Use the new time display format
                    echo "</div>";
                }
            }
        }
        
        echo "</td>";
        echo "</tr>";
    }

    echo "</tbody></table>";
}

// DAY NAV
function renderDayNavigation(
    int $month,
    int $year,
    int $day,
    string $lang = 'en',
    array $translations = []
): void {
    // Check if the language exists in the translations, otherwise use 'en'
    $translations[$lang] = $translations[$lang] ?? $translations['en'];

    // Retrieve the translated navigation terms
    $navTexts = $translations[$lang]['navigation'];

    // Create a DateTimeImmutable object for the current date
    $currentDate = new DateTimeImmutable("$year-$month-$day");

    // Calculate the previous and next day
    $prevDate = $currentDate->modify('-1 day');
    $nextDate = $currentDate->modify('+1 day');

    // Display the navigation with translated terms
    echo "<div class='calendar-navigation'>";
    echo "<a href='?year={$prevDate->format('Y')}&month={$prevDate->format('m')}&day={$prevDate->format('d')}&view=day'>&lt; {$navTexts['previous_day']}</a>";
    echo " | <a href='?year=" . date('Y') . "&month=" . date('m') . "&day=" . date('d') . "&view=day'>{$navTexts['today']}</a> | ";
    echo "<a href='?year={$nextDate->format('Y')}&month={$nextDate->format('m')}&day={$nextDate->format('d')}&view=day'>{$navTexts['next_day']} &gt;</a>";
    echo "</div>";
}


// YEAR VIEW
function renderYearCalendar(
    int $year, 
    array $events, 
    string $weekStart = 'monday', 
    string $lang = 'en', 
    array $translations = []
): void {
    // Displays the title of the year
    echo "<h2>$year</h2>";
    echo "<div class='calendar-year'>";

    // Current date
    $today = new DateTimeImmutable();

    // Loop through the 12 months of the year
    for ($month = 1; $month <= 12; $month++) {
        echo "<div class='calendar-year-month'>";
        
        // Displays the name of the month
        $monthName = $translations[$lang]['months']['long'][$month - 1] ?? date('F', mktime(0, 0, 0, $month, 1));
        echo "<h3>$monthName $year</h3>";
        
        // Calculate the number of days in the month and the first day of the month
        $numDays = cal_days_in_month(CAL_GREGORIAN, $month, $year);
        $firstDayOfMonth = new DateTimeImmutable("$year-$month-01");
        $firstDayOfWeek = (int) $firstDayOfMonth->format('N');
        
        // Calculates the offset based on the start day of the week
        $startOffset = $weekStart === 'sunday' ? $firstDayOfWeek % 7 : $firstDayOfWeek - 1;
        
        // Displays the header of the days of the week
        echo "<table class='calendar-month'><thead><tr>";
        $daysOfWeek = $weekStart === 'sunday' 
            ? $translations[$lang]['days']['short'] 
            : array_merge(array_slice($translations[$lang]['days']['short'], 1), array_slice($translations[$lang]['days']['short'], 0, 1));
        foreach ($daysOfWeek as $day) {
            echo "<th>$day</th>";
        }
        echo "</tr></thead><tbody><tr>";
        
        // Displays the days of the month with `renderMonthDayCell`
        
        // Days of the previous month to complete the first week
        for ($i = $startOffset - 1; $i >= 0; $i--) {
            echo "<td class='prev-month'></td>"; // Empty cells for the previous month
        }

        // Days of the current month
        for ($day = 1; $day <= $numDays; $day++) {
            // Determine if the current day is today
            $class = '';
            if ($year === (int)$today->format('Y') && $month === (int)$today->format('m') && $day === (int)$today->format('d')) {
                $class = 'today'; // Add 'today' class if it's the current day
            }
            renderMonthDayCell($year, $month, $day, $events, $class, true); // Call with `$isYearView = true`
            
            // Start a new row if the week is complete
            if (($day + $startOffset) % 7 === 0) {
                echo "</tr><tr>";
            }
        }

        // Cells for the days of the next month to complete the last week
        $remainingCells = (7 - (($numDays + $startOffset) % 7)) % 7;
        for ($i = 1; $i <= $remainingCells; $i++) {
            echo "<td class='next-month'></td>"; // Empty cells for the next month
        }

        echo "</tr></tbody></table>";
        echo "</div>"; // End of the month
    }

    echo "</div>"; // End of the year
}

// YEAR NAV
function renderYearNavigation(
    int $year,
    string $lang = 'en',
    array $translations = []
): void {
    // Checks if the language exists in the translations, otherwise uses 'en'
    $translations[$lang] = $translations[$lang] ?? $translations['en'];

    // Retrieves the translated navigation terms
    $navTexts = $translations[$lang]['navigation'];

    // Displays the navigation with translated terms
    echo "<div class='calendar-navigation'>";
    echo "<a href='?year=" . ($year - 1) . "&view=year'>&lt; {$navTexts['previous_year']}</a>";
    echo " | <a href='?year=" . date('Y') . "&view=year'>{$navTexts['this_year']}</a> | ";
    echo "<a href='?year=" . ($year + 1) . "&view=year'>{$navTexts['next_year']} &gt;</a>";
    echo "</div>";
}
