class Person:
    def __init__(self, name: str, age: int, email: str) -> None:
        self._name: str = name
        self._age: int = age
        self._email: str = email

    def get_details(self) -> str:
        return f"Name: {self._name}, Age: {self._age}, Email: {self._email}"


class Student(Person):
    def __init__(self, name: str, age: int, email: str, student_id: int) -> None:
        super().__init__(name, age, email)
        self._student_id: int = student_id
        self._courses: list = []
        self._grades: dict[str, str] = {}

    def enroll_in_course(self, course: 'Course') -> None:
        self._courses.append(course)
    
    def assign_grade(self, course_name: str, grade: str) -> None:
        self._grades[course_name] = grade

    def get_grades(self) -> dict[str, str]: 
        return self._grades


class Teacher(Person):
    def __init__(self, name: str, age: int, email: str, subject: str) -> None:
       super().__init__(name, age, email)
       self._subject: str = subject

    def assign_grade(self, student: Student, course: 'Course', grade: str) -> None:
        student.assign_grade(course._course_name, grade)

class Course:
    def __init__(self, course_name: str, course_code: str) -> None:
        self._course_name: str = course_name
        self._course_code: str = course_code
        self._enrolled_students: list[Student] = []

    def add_student(self, student: Student) -> None: 
        self._enrolled_students.append(student)
        student.enroll_in_course(self)
    
    def list_students(self) -> list[str]: 
        return [x.get_details() for x in self._enrolled_students]

def main() -> None:
    thorvald = Student("Thorvald", 28, "thorvald@example.com", 456)
    johannes = Student("Johannes", 19, "Johannes@example.com", 35198)
    tora = Student("Tora", 21, "Tora@example.com", 984555)

    ola = Teacher("Ola Normann", 56, "ola_normann@example.com", "FYS101")
    kari = Teacher("Kari Normann", 104, "kari.normann@example.com", "MATH999")

    FYS101 = Course("Mekanikk", "FYS101")
    MATH999 = Course("Matte", "MATH999")

    students = [thorvald, johannes, tora]

    for student in students:
        FYS101.add_student(student)
        MATH999.add_student(student)

    ola.assign_grade(thorvald, FYS101, "F")
    ola.assign_grade(johannes, FYS101, "E")
    ola.assign_grade(tora, FYS101, "A")

    kari.assign_grade(thorvald, MATH999, "B")
    kari.assign_grade(johannes, MATH999, "D")
    kari.assign_grade(tora, MATH999, "A+")

    print(f"{thorvald._name}'s grades: {thorvald.get_grades()}")
    print(f"{thorvald._name}'s grades: {johannes.get_grades()}")
    print(f"{tora._name}'s grades: {tora.get_grades()}")

    print("Students in FYS101:")
    for student in FYS101.list_students():
        print(student)

if __name__ == "__main__":
    main()
