digraph ClassDiagram {
    graph [
        rankdir="TB",
        splines=ortho,
        nodesep=1.0,
        ranksep=1.2
    ];
    node [
        shape=record,
        style=filled,
        fillcolor=lightyellow,
        fontname="Helvetica,Arial,sans-serif"
    ];
    edge [
        fontname="Helvetica,Arial,sans-serif"
    ];

    // --- Interfaces ---
    IReservation [
        label="{interface\nIReservation|+ ReservationType(): String\l+ checkValid(): boolean\l+ calculatePrice(): float\l+ getReservation_number(): String\l+ getPhysical_address(): Address\l+ getAccountNumber(): String\l}",
        fillcolor=palegreen
    ];

    // --- Abstract Classes ---
    Reservation [
        label="{abstract\nReservation|+ {abstract} ReservationType(): String\l+ Write(Reservation): void\l+ Change(Reservation, ReservationStatusEnum): void\l+ update(Reservation): void\l+ calculatePrice(): float\l+ setMailing_address(Address): void\l+ setNumberOfBeds(int): void\l+ setNumberOfFloors(int): void\l+ setNumberOfBedRooms(int): void\l+ setSquareFeet(int): void\l+ setReservation_start_date(ZonedDateTime): void\l+ setReservation_end_date(ZonedDateTime): void\l}",
        fontstyle=italic
    ];

    // --- Concrete Classes ---
    AccomodationManager [
        label="{AccomodationManager|+ AccomodationManager(String)\l+ loadAll(): void\l+ retrieveAccount(String): Account\l+ retrieveLoadedAccounts(): AccountList\l+ newAccount(String, Address, EmailAddress): Account\l+ AddAccount(Account): void\l+ UpdateAccount(Account): void\l+ addReservation(Account, Reservation): boolean\l+ showReservationList(): void\l}"
    ];

    DataRepository [
        label="{DataRepository (Singleton)|+ {static} getInstance(): DataRepository\l+ {static} setDataStoreRoot(String): void\l+ {static} WalkFileSystemTree(AccomodationManager, Path): void\l+ {static} LoadAccount(Path): Account\l}",
        fillcolor=orchid
    ];

    Account [
        label="{Account|+ add(Reservation): boolean\l+ findReservation(String): Reservation\l+ getAllReservations(): Iterator\l+ getAccount_number(): String\l+ {static} Write(Account): void\l}"
    ];

    AccountList [
        label="{AccountList|+ add(Account): boolean\l+ find(String): Account\l+ save(Account): void\l}"
    ];

    AccountReservationList [
        label="{AccountReservationList|+ add(IReservation): boolean\l+ find(String): Reservation\l}"
    ];

    HotelReservation [
        label="{HotelReservation|+ HotelReservation(Address)\l+ calculatePrice(): float\l}"
    ];
    CabinReservation [
        label="{CabinReservation|+ CabinReservation(Address)\l+ calculatePrice(): float\l}"
    ];
    HouseReservation [
        label="{HouseReservation|+ HouseReservation(Address)\l+ calculatePrice(): float\l}"
    ];

    TestReservations [
        label="{TestReservations|+ {static} main(String[]): void\l}"
    ];
    
    "TestReservations.getRepositoryConfig" [
        label="{static class\ngetRepositoryConfig|+ {static} getPath(): String\l}"
    ];

    // --- Data/Enum/Exception Classes ---
    Address [label="{Address|+ Address(String, String, String, String)\l}", fillcolor=lightblue];
    EmailAddress [label="{EmailAddress|+ EmailAddress(String)\l}", fillcolor=lightblue];
    ReservationStatusEnum [label="{enum\nReservationStatusEnum}", fillcolor=lightgray];
    DuplicateObjectException [label="{exception\nDuplicateObjectException}", fillcolor=lightpink];

    // --- Relationships ---

    // Inheritance / Implementation
    Reservation -> IReservation [arrowhead=empty, style=dashed, label="implements"];
    HotelReservation -> Reservation [arrowhead=empty, label="extends"];
    CabinReservation -> Reservation [arrowhead=empty, label="extends"];
    HouseReservation -> Reservation [arrowhead=empty, label="extends"];

    // Composition / Aggregation
    AccomodationManager -> AccountList [arrowhead=diamond, label="has a"];
    AccountList -> Account [arrowhead=odiamond, label="0..*"];
    Account -> AccountReservationList [arrowhead=diamond, label="has a"];
    AccountReservationList -> IReservation [arrowhead=diamond, label="0..*"];
    Account -> Address [arrowhead=odiamond, label="mailing"];
    Account -> EmailAddress [arrowhead=odiamond];
    Reservation -> Address [arrowhead=odiamond, label="physical/mailing"];

    // Dependencies
    TestReservations -> AccomodationManager [arrowhead=vee, style=dashed, label="uses"];
    TestReservations -> "TestReservations.getRepositoryConfig" [arrowhead=vee, style=dashed, label="uses"];
    TestReservations -> HotelReservation [arrowhead=vee, style=dashed, label="creates"];
    TestReservations -> CabinReservation [arrowhead=vee, style=dashed, label="creates"];
    TestReservations -> HouseReservation [arrowhead=vee, style=dashed, label="creates"];
    TestReservations -> Account [arrowhead=vee, style=dashed, label="uses"];
    TestReservations -> Address [arrowhead=vee, style=dashed, label="creates"];
    TestReservations -> EmailAddress [arrowhead=vee, style=dashed, label="creates"];
    TestReservations -> DuplicateObjectException [arrowhead=vee, style=dashed, label="catches"];
    
    AccomodationManager -> DataRepository [arrowhead=vee, style=dashed, label="uses"];
    AccomodationManager -> Account [arrowhead=vee, style=dashed, label="manages"];
    
    Account -> DataRepository [arrowhead=vee, style=dashed, label="uses for Write()"];
    Reservation -> DataRepository [arrowhead=vee, style=dashed, label="uses for Write()"];
    Reservation -> ReservationStatusEnum [arrowhead=vee, style=dashed, label="uses"];
}
