#! /usr/bin/env python
"""
Description:
    Programm zur Ausgabe einer Ansicht eines Monats wie gängige Kalender-Format

Usage:

```
$ python month_of_year-no-fn.py 12 2024
```
"""

from typing import Final
import sys

month: Final[int] = int(sys.argv[1])
year: Final[int] = int(sys.argv[2])

# Calender setup
weekdays: Final[tuple[str, ...]] = ("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa")
first_day_of_week: Final[int] = 1  # it is monday, common in Europa
months: Final[tuple[ tuple[str, int], ...]] = (("", 0),
                                             ("Januar", 31), ("Februar", 28), ("März", 31),
                                             ("April", 30), ("Mai", 31), ("Juni", 30),
                                             ("July", 31), ("August", 31), ("September", 30),
                                             ("Oktober", 31), ("November", 30), ("Dezember", 31))


# calculate the weekday of the 1.st day of the given month
# Not possible to test next lines of code, since all variables are global
first_date: Final[int] = 1  # first day of the month
y0 = year - ((14 - month)//12)
x = y0 + (y0//4) - (y0//100) + (y0//400)
m0 = month + 12 * ((14 - month)//12) - 2
day_of_first_date = (first_date + x + (31 * m0) // 12) % 7

# test and comment out
# print(weekdays[first_day_of_month])

# calculate how many days of last month get places in the first week
# of this month
diff: Final[int] = (7 + day_of_first_date - first_day_of_week) % 7
# test and comment out
# print(diff)

# calculate how many days in the month
days_in_months = months[month][1]
# check leap year
if month == 2:
    if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
        days_in_months += 1


# print the calendar
column_width: Final[int] = 5  # at least 3, since days in month have at most 2 digits
calendar_width: Final[int] = 7 * column_width  # 7 days of a week, each day need 3 spaces
head_line = f"{months[month][0]} {year}"
fmt_head_line = f"{head_line}".center(calendar_width, '-')
# test and comment out
# print(fmt_head_line)

# calender_view is initialized with Headline
calendar_view: str = fmt_head_line + "\n"

# 7 weekdays
for d in weekdays:
    calendar_view += f"{d}".rjust(column_width, ' ')
# test and comment out
calendar_view += "\n"
# print(calendar_view)

# the empty columns in the first week of the month
for _ in range(diff, 0, -1):
    calendar_view += ("#"*(column_width-1) + "-")  # mark empty columns with some characters to let debug easier

# print the days in the first week
day = 1
days_in_first_week = ""
while day + diff <= 7:
    days_in_first_week += (f"{day}".rjust(column_width))
    day += 1
calendar_view += days_in_first_week + "\n"

while day <= days_in_months:
    calendar_view += (f"{day}".rjust(column_width))
    if (day + diff) % 7 == 0:  # reaches the last day of week
        calendar_view += "\n"
    day += 1

print(calendar_view)