1use std::fmt;
2
3use thedes_tui::{
4 core::event::Key,
5 menu::{self, Menu},
6};
7use thiserror::Error;
8
9use crate::session;
10
11pub mod new_game;
12pub mod game_creation;
13
14#[derive(Debug, Error)]
15pub enum InitError {
16 #[error("Failed to initialize main menu")]
17 MainMenu(
18 #[from]
19 #[source]
20 menu::Error,
21 ),
22 #[error("Failed to initialize new game component")]
23 NewGame(
24 #[from]
25 #[source]
26 new_game::InitError,
27 ),
28 #[error("Inconsistent main menu, missing quit")]
29 MissingQuit,
30}
31
32#[derive(Debug, Error)]
33pub enum Error {
34 #[error("Failed to run main menu")]
35 MainMenu(
36 #[from]
37 #[source]
38 menu::Error,
39 ),
40 #[error("Failed to run new game component")]
41 NewGame(
42 #[from]
43 #[source]
44 new_game::Error,
45 ),
46 #[error("Failed to run game creation")]
47 GameCreation(
48 #[from]
49 #[source]
50 game_creation::Error,
51 ),
52 #[error("Failed to run game session component")]
53 Session(
54 #[from]
55 #[source]
56 session::Error,
57 ),
58 #[error("Failed to create a game session")]
59 SessionInit(
60 #[from]
61 #[source]
62 session::InitError,
63 ),
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67enum MainMenuItem {
68 NewGame,
69 LoadGame,
70 Settings,
71 Quit,
72}
73
74impl fmt::Display for MainMenuItem {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 f.write_str(match self {
77 Self::NewGame => "New Game",
78 Self::LoadGame => "Load Game",
79 Self::Settings => "Settings",
80 Self::Quit => "Quit",
81 })
82 }
83}
84
85#[derive(Debug, Clone)]
86pub struct Component {
87 main_menu: Menu<MainMenuItem>,
88 new_game: new_game::Component,
89 game_creation: game_creation::Component,
90 session_config: session::Config,
91}
92
93impl Component {
94 pub fn new() -> Result<Self, InitError> {
95 let main_menu_items = [
96 MainMenuItem::NewGame,
97 MainMenuItem::LoadGame,
98 MainMenuItem::Settings,
99 MainMenuItem::Quit,
100 ];
101
102 let quit_position = main_menu_items
103 .iter()
104 .position(|item| *item == MainMenuItem::Quit)
105 .ok_or(InitError::MissingQuit)?;
106
107 let main_menu_bindings = menu::default_key_bindings()
108 .with(Key::Char('q'), menu::Command::SelectConfirm(quit_position));
109
110 let main_menu = Menu::new("=== T H E D E S ===", main_menu_items)?
111 .with_keybindings(main_menu_bindings);
112
113 let new_game = new_game::Component::new()?;
114 let game_creation = game_creation::Component::new();
115
116 Ok(Self {
117 main_menu,
118 new_game,
119 game_creation,
120 session_config: session::Config::new(),
121 })
122 }
123
124 pub async fn run(
125 &mut self,
126 app: &mut thedes_tui::core::App,
127 ) -> Result<(), Error> {
128 loop {
129 self.main_menu.run(app).await?;
130
131 match self.main_menu.output() {
132 MainMenuItem::NewGame => {
133 self.new_game.run(app).await?;
134 let seed = self.new_game.form().seed;
135 let config = thedes_gen::Config::new().with_seed(seed);
136 if let Some(game) =
137 self.game_creation.run(app, config).await?
138 {
139 let mut session =
140 self.session_config.clone().finish(game)?;
141 session.run(app).await?;
142 }
143 },
144
145 MainMenuItem::LoadGame => {},
146 MainMenuItem::Settings => {},
147 MainMenuItem::Quit => break,
148 }
149 }
150
151 Ok(())
152 }
153}