use std::io;
use std::sync::{Arc, Mutex};
use ratatui::DefaultTerminal;
use serde::Deserialize;
use crate::config::Config;
use crate::events;
use crate::key_bindings::Keybindings;
use crate::service::Service;
use crate::service_groups::ServiceGroup;
use crate::ui::ui;
#[derive(Debug, Deserialize)]
pub struct App {
pub service_groups: Vec<ServiceGroup>,
pub cursor: usize,
pub current_screen: CurrentScreen,
pub services: Vec<Arc<Mutex<Service>>>,
pub key_bindings: Keybindings,
pub exit: bool,
}
#[derive(Debug, Deserialize, PartialEq, Clone)]
pub enum CurrentScreen {
MainMenu,
KeyBindings { previous_screen: Box<CurrentScreen> },
CreatingNew { text: String },
RenameGroup { text: String },
GroupView { index: usize },
ServiceSelection { group_index: usize, text: String },
ServiceLogs { group_index: usize, index: usize, log_scroll: usize },
}
impl App {
pub fn init() -> io::Result<Self> {
let mut app = App {
service_groups: vec![],
cursor: 0,
current_screen: CurrentScreen::MainMenu,
services: Service::get_all(),
key_bindings: Keybindings::default(),
exit: false,
};
Config::load_config(&mut app)?;
Ok(app)
}
pub fn run(&mut self, terminal: &mut DefaultTerminal) -> io::Result<()> {
terminal.clear()?;
while !self.exit {
terminal.draw(|frame| ui(frame, self))?;
events::handle_events(self)?;
}
Ok(())
}
pub fn help(&mut self) {
self.current_screen = CurrentScreen::KeyBindings {
previous_screen: Box::new(self.current_screen.clone()),
};
}
pub fn submit_new(&mut self, text: String) {
let service_group = ServiceGroup::new(text);
self.service_groups.push(service_group);
self.cursor = self.service_groups.len() - 1;
self.current_screen = CurrentScreen::MainMenu;
}
pub fn rename_group(&mut self) {
let group_name = self.service_groups[self.cursor].name.clone();
self.current_screen = CurrentScreen::RenameGroup { text: group_name };
}
pub fn submit_rename(&mut self, text: String) {
self.service_groups[self.cursor].name = text;
self.current_screen = CurrentScreen::MainMenu;
}
pub fn duplicate_group(&mut self) {
let group = self.service_groups[self.cursor].clone();
let name = group.name.clone();
self.service_groups.push(group);
self.cursor = self.service_groups.len() - 1;
self.current_screen = CurrentScreen::RenameGroup { text: name };
}
pub fn save(&mut self) -> io::Result<()> {
Config::save_config(self)
}
pub fn delete_group(&mut self) {
self.service_groups.remove(self.cursor);
if self.service_groups.len() != 0 && self.cursor >= self.service_groups.len() {
self.cursor = self.service_groups.len() - 1;
}
}
pub fn exit(&mut self) {
self.exit = true;
}
pub fn reload(&mut self) -> io::Result<()> {
Config::load_config(self)
}
pub fn list_service_groups(&mut self) {
for (index, group) in self.service_groups.iter().enumerate() {
print!("{}: {}\n", index+1, group.name);
}
}
pub fn next_group(&mut self) {
if self.cursor == self.service_groups.len() - 1 {
self.cursor = 0;
} else {
self.cursor += 1;
}
}
pub fn previous_group(&mut self) {
if self.cursor == 0 {
self.cursor = self.service_groups.len() - 1;
} else {
self.cursor -= 1;
}
}
pub fn select_group(&mut self) {
self.current_screen = CurrentScreen::GroupView { index: self.cursor };
}
pub fn toggle_activate(&mut self, name: Option<String>) -> io::Result<bool> {
if let Some(name) = name {
for (index, group) in self.service_groups.iter_mut().enumerate() {
if group.name == name.to_lowercase() {
self.cursor = index;
break;
}
}
}
if let Some(group) = self.service_groups.get_mut(self.cursor) {
group.toggle_active()
} else {
Err(io::Error::new(
io::ErrorKind::NotFound,
"No service group found",
))
}
}
pub fn toggle_enabled(&mut self, name: Option<String>) -> io::Result<bool> {
if let Some(name) = name {
for (index, group) in self.service_groups.iter_mut().enumerate() {
if group.name == name.to_lowercase() {
self.cursor = index;
break;
}
}
}
if let Some(group) = self.service_groups.get_mut(self.cursor) {
group.toggle_enabled()
} else {
Err(io::Error::new(
io::ErrorKind::NotFound,
"No service group found",
))
}
}
}