From 96e7d06ef2d84de2223abb87b9b365d185b6b0db Mon Sep 17 00:00:00 2001
From: Midnight Exigent <6959267-midnightexigent@users.noreply.gitlab.com>
Date: Fri, 16 Jul 2021 22:41:12 +0200
Subject: [PATCH] initial implementation of `Preset`

---
 src/config/window_definition.rs | 91 +++++++++++++++++++++++++++++++--
 1 file changed, 86 insertions(+), 5 deletions(-)

diff --git a/src/config/window_definition.rs b/src/config/window_definition.rs
index e2c85ec86..34ea62d39 100644
--- a/src/config/window_definition.rs
+++ b/src/config/window_definition.rs
@@ -3,7 +3,78 @@ use crate::{ensure_xml_tag_is, enum_parse, value::NumWithUnit, widgets::widget_n
 use derive_more::*;
 use serde::{Deserialize, Serialize};
 use smart_default::SmartDefault;
-use std::{collections::HashMap, str::FromStr};
+use std::{collections::HashMap, convert::TryFrom, str::FromStr};
+
+pub mod preset {
+    use super::{Result, Side, XmlElement};
+
+    #[non_exhaustive]
+    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
+    // #[derive(Serialize, Deserialize)]
+    // #[serde(untagged)] if serde becomes an option
+    pub enum Preset {
+        Bar(Bar),
+        Floating(Floating),
+    }
+    impl Preset {
+        pub fn from_xml_element(xml: &XmlElement) -> Result<Self> {
+            Bar::from_xml_element(xml).map(Self::Bar).or_else(|_| Floating::from_xml_element(xml).map(Self::Floating))
+        }
+    }
+
+    #[non_exhaustive]
+    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
+    pub struct Bar {
+        side: Side,
+    }
+    impl Bar {
+        fn from_xml_element(xml: &XmlElement) -> Result<Self> {
+            Ok(Bar { side: xml.attr("side")?.parse()? })
+        }
+    }
+
+    #[non_exhaustive]
+    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
+    pub struct Floating {}
+    impl Floating {
+        fn from_xml_element(xml: &XmlElement) -> Result<Self> {
+            Ok(Floating {})
+        }
+    }
+}
+use preset::Preset;
+impl TryFrom<Option<&Preset>> for WindowStacking {
+    type Error = anyhow::Error;
+
+    fn try_from(value: Option<&Preset>) -> Result<Self, Self::Error> {
+        todo!()
+    }
+}
+impl TryFrom<Option<&Preset>> for WindowName {
+    type Error = std::convert::Infallible;
+
+    fn try_from(value: Option<&Preset>) -> Result<Self, Self::Error> {
+        match value {
+            Some(Preset::Bar(bar)) => Ok(WindowName(format!("Eww - {:?}", bar))),
+            Some(Preset::Floating(floating)) => Ok(WindowName(format!("Eww - {:?}", floating))),
+            None => Ok(WindowName("Eww - Window".to_string())),
+        }
+    }
+}
+impl TryFrom<Option<&Preset>> for EwwWindowGeometry {
+    type Error = anyhow::Error;
+
+    fn try_from(value: Option<&Preset>) -> Result<Self, Self::Error> {
+        todo!()
+    }
+}
+impl TryFrom<Option<&Preset>> for BackendWindowOptions {
+    type Error = anyhow::Error;
+
+    fn try_from(value: Option<&Preset>) -> Result<Self, Self::Error> {
+        todo!()
+    }
+}
 
 /// Full window-definition containing the fully expanded widget tree.
 /// **Use this** rather than [RawEwwWindowDefinition].
@@ -48,20 +119,30 @@ pub struct RawEwwWindowDefinition {
 impl RawEwwWindowDefinition {
     pub fn from_xml_element(xml: &XmlElement) -> Result<Self> {
         ensure_xml_tag_is!(xml, "window");
+        // let preset = Preset::from_xml_element(xml)?;
+        let preset = None::<Preset>;
+
         let geometry = match xml.child("geometry") {
             Ok(node) => Some(EwwWindowGeometry::from_xml_element(node)?),
-            Err(_) => None,
+            Err(_) => match EwwWindowGeometry::try_from(preset.as_ref()) {
+                Ok(geometry) => Some(geometry),
+                Err(_) => None,
+            },
         };
 
         Ok(RawEwwWindowDefinition {
-            name: WindowName(xml.attr("name")?),
+            name: xml.attr("name").map(WindowName).or_else(|_| WindowName::try_from(preset.as_ref()))?,
             geometry,
             widget: WidgetUse::from_xml_node(xml.child("widget")?.only_child()?)?,
-            stacking: xml.parse_optional_attr("stacking")?.unwrap_or_default(),
+            stacking: xml
+                .parse_optional_attr("stacking")?
+                .or_else(|| WindowStacking::try_from(preset.as_ref()).ok())
+                .unwrap_or_default(),
             // TODO maybe rename this to monitor?
             screen_number: xml.parse_optional_attr("screen")?,
             resizable: xml.parse_optional_attr("resizable")?.unwrap_or(true),
-            backend_options: BackendWindowOptions::from_xml_element(xml)?,
+            backend_options: BackendWindowOptions::from_xml_element(xml)
+                .or_else(|_| BackendWindowOptions::try_from(preset.as_ref()))?,
         })
     }
 }