1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use crate::paths;
use factorio_bot_core::miette::{IntoDiagnostic, Result};
use factorio_bot_core::serde::{Deserialize, Serialize};
use factorio_bot_core::serde_json;
use factorio_bot_core::serde_json::Value;
use factorio_bot_core::settings::FactorioSettings;
#[cfg(feature = "restapi")]
use factorio_bot_restapi::settings::RestApiSettings;
use std::borrow::Cow;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use tokio::sync::RwLock;

#[allow(clippy::module_name_repetitions)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct GuiSettings {
  pub enable_autostart: bool,
  pub enable_restapi: bool,
}

#[allow(clippy::module_name_repetitions)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct AppSettings {
  pub factorio: FactorioSettings,
  #[cfg(feature = "restapi")]
  pub restapi: RestApiSettings,
  pub gui: GuiSettings,
}

#[allow(clippy::module_name_repetitions)]
pub type SharedAppSettings = Arc<RwLock<AppSettings>>;

impl AppSettings {
  pub fn into_shared(self) -> SharedAppSettings {
    Arc::new(RwLock::new(self))
  }
  pub fn load(file_path: PathBuf) -> Result<AppSettings> {
    if Path::exists(&file_path) {
      let file_contents = ::std::fs::read_to_string(file_path).into_diagnostic()?;
      let mut app_settings = serde_json::to_value(AppSettings::default()).into_diagnostic()?;
      let result: Value = ::toml::from_str(&file_contents).into_diagnostic()?;
      AppSettings::merge(&mut app_settings, &result);
      Ok(serde_json::from_value(app_settings).into_diagnostic()?)
    } else {
      Ok(AppSettings::default())
    }
  }

  #[allow(dead_code)]
  pub fn save(file_path: PathBuf, app_settings: &AppSettings) -> Result<()> {
    let file_contents = ::toml::to_string(app_settings).into_diagnostic()?;
    ::std::fs::write(file_path, file_contents).into_diagnostic()?;
    Ok(())
  }

  fn merge(a: &mut Value, b: &Value) {
    match (a, b) {
      (&mut Value::Object(ref mut a), &Value::Object(ref b)) => {
        for (k, v) in b {
          AppSettings::merge(a.entry(k.clone()).or_insert(Value::Null), v);
        }
      }
      (a, b) => {
        *a = b.clone();
      }
    }
  }
}

#[allow(clippy::module_name_repetitions)]
pub fn load_app_settings() -> Result<AppSettings> {
  let mut app_settings = AppSettings::load(paths::settings_file())?;
  if app_settings.factorio.workspace_path == "" {
    let s: String = paths::workspace_dir().to_str().unwrap().into();
    app_settings.factorio.workspace_path = Cow::from(s);
  }
  Ok(app_settings)
}