//Calendar implementation for the HTWK Leipzig timetable. Evaluation and display of the individual dates in iCal format.
//Copyright (C) 2024 HTWKalender support@htwkalender.de

//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU Affero General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU Affero General Public License for more details.

//You should have received a copy of the GNU Affero General Public License
//along with this program.  If not, see <https://www.gnu.org/licenses/>.

package date

import (
	"log/slog"
	"strconv"
	"strings"
	"time"
	_ "time/tzdata"
)

func GetDateFromWeekNumber(year int, weekNumber int, dayName string) (time.Time, error) {
	// Create a time.Date for the first day of the year
	europeTime, err := time.LoadLocation("Europe/Berlin")

	if err != nil {
		slog.Error("Failed to load location: ", "error", err)
		return time.Time{}, err
	}

	firstDayOfYear := time.Date(year, time.January, 1, 0, 0, 0, 0, europeTime)

	// Calculate the number of days to add to reach the desired week
	daysToAdd := time.Duration((weekNumber-1)*7) * 24 * time.Hour

	// Find the starting day of the week (e.g., Monday)
	startingDayOfWeek := firstDayOfYear

	// check if the first day of the year is friday or saturday or sunday

	if startingDayOfWeek.Weekday() == time.Friday || startingDayOfWeek.Weekday() == time.Saturday || startingDayOfWeek.Weekday() == time.Sunday {
		for startingDayOfWeek.Weekday() != time.Monday {
			startingDayOfWeek = startingDayOfWeek.Add(24 * time.Hour)
		}
	} else {
		for startingDayOfWeek.Weekday() != time.Monday {
			startingDayOfWeek = startingDayOfWeek.Add(-24 * time.Hour)
		}
	}

	// Calculate the desired date by adding daysToAdd and adjusting for the day name
	desiredDate := startingDayOfWeek.Add(daysToAdd)

	// Find the day of the week
	dayOfWeek := map[string]time.Weekday{
		"Montag":     time.Monday,
		"Dienstag":   time.Tuesday,
		"Mittwoch":   time.Wednesday,
		"Donnerstag": time.Thursday,
		"Freitag":    time.Friday,
		"Samstag":    time.Saturday,
		"Sonntag":    time.Sunday,
	}[dayName]

	// Adjust to the desired day of the week
	for desiredDate.Weekday() != dayOfWeek {
		desiredDate = desiredDate.Add(24 * time.Hour)
	}

	return desiredDate, nil
}

// createEventFromTableData should create an event from the table data
// tableTime represents Hour and Minute like HH:MM
// tableDate returns a Time
func CreateTimeFromHourAndMinuteString(tableTime string) time.Time {
	timeParts := strings.Split(tableTime, ":")
	hour, _ := strconv.Atoi(timeParts[0])
	minute, _ := strconv.Atoi(timeParts[1])
	return time.Date(0, 0, 0, hour, minute, 0, 0, time.UTC)
}
