@startuml
'Attribute syntax: <visibility> <name> : <type> <multiplicity> = <default>
'Method syntax: <visibility> <name (parameter-list)> : <return-type> - For simplicity the type of the parameter-list is not specified

skinparam classAttributeIconSize 0
'skinparam classBackgroundColor transparent
skinparam linetype polyline


' Controllers ----------------------------------------------------------------------------------------------------------
class CreateProfileController {
    -profileService : ProfileService

    +CreateProfileController ()
    +createProfile (name) : boolean
}

class ChangeProfileController {
    -profileService : ProfileService

    +ChangeProfileController ()
    +accountList () : String
    +profileList () : String
    +changeProfile (accountID, profileID) : boolean
}

class RegisterAccountController {
    -accountService : AccountService

    +RegisterAccountController ()
    +createAccount (name, email, photo, phoneNumber) : boolean
}

class ListAccountController {
    -accountService : AccountService

    +ListAccountController ()
    +accountsAndStatusList() : AccountListDTO
}

class InactivateAccountController {
    -accountService : AccountService

    +InactivateAccountController ()
    +inactivateAccount (accountID : UUID) : boolean
}

class ActivateAccountController {
    -accountService : AccountService

    +ActivateAccountController ()
    +activateAccount (accountID : UUID) : boolean
}

' Services -------------------------------------------------------------------------------------------------------------
class ProfileService {
    - {static} profileService : ProfileService
    -profile container : ProfileContainer

    -ProfileService ()
    + {static} getInstance() : Singleton
    - {static} destroyInstance ()
    +delete ()
    +createProfile (name) : boolean
    +validateProfile (profileID : String) : boolean
}

class AccountService {
    - {static} AccountService : accountService
    -accounts : AccountContainer

    -AccountService ()
    + {static} getInstance () : Singleton
    +createNewAccount (name, email, photo, phoneNumber) : boolean
    +delete ()
    - {static} destroyInstance ()
    -isValid (name, email) : boolean
    -isUnique (email) : boolean
    +activateAccount (accountID : UUID) : boolean
    +inactivateAccount (accountID : UUID) : boolean
    -isPhoneNumberValid (phoneNumber) : boolean
    -testEmailPattern (email) : boolean
    +changeProfile (accountID, profileID) : boolean
    +accountsAndStatusList () : accountsListDTO
    -validateUUID (id) : boolean
}

' Collections ----------------------------------------------------------------------------------------------------------
class ProfileContainer {
    -profiles : Profile [1..*] = [Admin]

    +ProfileContainer()
    +createProfile (name) : boolean
    +generateProfileDTO() : ProfileDTO []
    +validateProfileID (profileID : UUID) : boolean
}

class AccountContainer {
    -accounts : Account [1..*]

    +AccountContainer ()
    +createNewAccount (name, email, photo, phoneNumber) : boolean
    +addToAccounts (newAcc : Account)
    +searchAccount (accountID : UUID) : Account
    +inactivate (accountID : UUID) : boolean
    +activate (accountID : UUID) : boolean
    +generateAccountsDTO () : AccountDTO [1..*]
    +changeProfile (accountID, profileID) : boolean
    +accountsAndStatusList () : String
    +accountList () : String
    +isUnique (email) : boolean
    +accountHasProfile (accountID, profileID) : boolean

}

' Entities ----------------------------------------------------------------------------------------------------------------
class Profile {
    -id: UUID
    -name : String

    +Profile (name : String)
    +generateDTO () : ProfileDTO
    +hasID (id : UUID) : boolean
    +equals (Profile) : boolean
}

class Account {
    -id: UUID
    -name : String
    -email : String
    -photo : Image
    -phoneNumber : int
    -profileID : UUID
    -isActive : boolean = true

    +Account (name, email, photo, phoneNumber)
    +hasID (accountID : UUID) : boolean
    +inactivate () : boolean
    +activate () : boolean
    +generateDTO () : AccountDTO
    +sameEmail (email) : boolean
    +changeProfile (profileID : UUID) : boolean
    +equals (Account) : boolean
}

' Assembler ------------------------------------------------------------------------------------------------------------
class AccountListAssembler {
    -accountDTOCollection : AccountDTO

    +AccountListAssembler ()
    +createDTO (accountContainer : AccountContainer) : AccountListDTO
}

class ProfileListAssembler {
    -profileListDTO : ProfileListDTO

    +ProfileListAssembler()
}

' DTO ------------------------------------------------------------------------------------------------------------------
class AccountDTO {
    -id: UUID
    -name : String
    -email : String
    -isActive : boolean

    +AccountDTO (id, name, email, status)
    +getID () : UUID
    +getName () : String
    +getEmail () : String
    +getStatus () : String
    +getProfile () : UUID
    +equals (object : AccountDTO)
}

class ProfileDTO {
    -id: UUID
    -name : String

    +ProfileDTO (id, name)
    +getID () : id
    +getName () : String
}

class AccountListDTO {
    -accountListDTO : AccountDTO [1..*]

    +AccountListDTO (AccountDTOCollection [1..*])
    +equals (AccountListDTO) : boolean
}

class ProfileListDTO {
    -profileDTOList : ProfileDTO [1..*]

    +ProfileListDTO ()
    +equals (ProfileListDTO) : boolean
}

' Associations and dependencies ----------------------------------------------------------------------------------------

' Controller Layer
CreateProfileController --> ProfileService : profileService
ChangeProfileController --> ProfileService : profileService
ChangeProfileController --> AccountService : accountService
RegisterAccountController --> AccountService : accountService
ListAccountController --> AccountService : accountService
InactivateAccountController --> AccountService : accountService
ActivateAccountController --> AccountService : accountService

' Service Layer
AccountService --> AccountContainer : accounts
ProfileService --> ProfileContainer : profiles

' Collections Layer
ProfileContainer "1" *--> "*" Profile : profiles
AccountContainer "1" *--> "*" Account : accounts

' DTO Layer
AccountService .l.> AccountListAssembler
AccountListAssembler ..> AccountContainer
AccountListAssembler ..> AccountDTO
AccountListAssembler --> AccountListDTO : accountListDTO
Account ..> AccountDTO

ProfileService .l.> ProfileListAssembler
ProfileListAssembler ..> ProfileContainer
ProfileListAssembler --> ProfileListDTO : profileListDTO
ProfileListAssembler ..> ProfileDTO
Profile ..> ProfileDTO


@enduml
