Author: Seph Pace
Email:  sephpace@gmail.com

@startuml

class Card
{
    - answers: vector<string>
    - definition: string
    - hint: string
    - id: long
    + Card()
    + Card(id: long, answers: vector<string>, definition: string)
    + Card(id: long, answers: vector<string>, definition: string, hint: string)
    + check_answer(answer: string): bool
    + get_answers(): vector<string>
    + get_definition(): string
    + get_hint(): string
    + get_id(): long
    + operator>(card: Card): bool 
    + operator<(card: Card): bool
    + operator>>(stream: istream, card: Card): istream
    + operator<<(stream: ostream, card: Card): ostream
}

class Deck
{
    - cards: vector<Card>
    - name: string
    + Deck(name: string)
    + ~Deck()
    + add(card: Card): void
    + add_all(cards: vector<Card>): void
    + clear(): void
    + draw(): Card
    + get_name(): string
    + load(name: string): bool
    + save(): void
    + shuffle(): void
    + size(): int
    + sort(): void
}

class Quizzer
{
    - card: Card
    - correct: int
    - deck: Deck
    - discard: vector<Card>
    - incorrect: int
    - skipped: int
    - stopped: bool
    - info_bar: Window
    - prompt_window: CenteredWindow
    - descr_window: CenteredWindow
    - input_bar: InputField
    - view: View
    + Quizzer(deck_name: string)
    + ~Quizzer()
    + start(): void
    + stop(): void
    # refresh(): void
    # update(): void
    - parse_command(command: string): bool
    - quiz(): void
}

class Editor
{
    - answer_windows: vector<EditableWindow>
    - card_index: long
    - card_view: View
    - card_windows: vector<Window>
    - deck_view: View
    - descr_window: CenteredEditableWindow
    + Editor()
    + ~Editor()
    # refresh(): void
    # update(): void
}

abstract class GUI
{
    - current_view: View
    - views: vector<View>
    + GUI()
    + ~GUI() 
    + {abstract} start(): void
    + {abstract} stop(): void
    # {abstract} refresh(): void
    # {abstract} update(): void
    - add_view(): void
    - display_view(view_id: long): void
}

class View
{
    - id: long
    - term_height: int
    - term_width: int
    - windows: vector<Window>
    + View()
    + ~View()
    + add_window(window: Window): void
    + clear_windows(): void
    + update(): void
    - check_resize(): void
    - resize_windows(): void
}

class Window
{
    + has_borders: bool
    + margin: int
    + padding: int
    + Window()
    + ~Window()
    + pause(): void
    + {abstract} print(text: string): void
    + {abstract} printf(template: string, ...): void
    + {abstract} refresh(): void
    - display_borders(): void
}

class CenteredWindow
{
    + CenteredWindow()
    + ~CenteredWindow()
    + {abstract} print(text: string): void
}

class EditableWindow
{
    + EditableWindow()
    + ~EditableWindow()
    + {abstract} edit(): void
    + {abstract} get_text(): string
    + {abstract} refresh(): void
}

class CenteredEditableWindow
{
    + CenteredEditableWindow()
    + ~CenteredEditableWindow()
    + {abstract} edit(): void
    + {abstract} get_text(): string
    + {abstract} print(text: string): void
    + {abstract} refresh(): void
}

class InputField
{
    + InputField()
    + ~InputField()
    + get_input(): string
}

class CLI
{
    + parse_args(args: string[]): int
    - create(deck_name: string): int
    - delete(deck_name: string): int
    - edit(deck_name: string): int
    - get_deck(deck_name: string): string
    - list(): int
    - quiz(deck_name: string): int
    - remove(deck_name: string, card_id: long): int
}


CLI "1" --> "1" Quizzer : Starts
CLI "1" --> "1" Editor : Starts
CLI "1" --> "*" Deck : Creates & Manipulates
Deck "1" --o "*" Card : Contains
Quizzer "1" --> "1" Deck : Manipulates
Editor "1" --> "1" Deck : Manipulates
GUI "1" --o "*" View : Contains
View "1" --o "*" Window: Contains

GUI <|-- Editor
GUI <|-- Quizzer
Window <|-- CenteredWindow
Window <|-- EditableWindow
Window <|-- InputField
CenteredWindow <|-- CenteredEditableWindow
EditableWindow <|-- CenteredEditableWindow

@enduml

