use std::collections::HashMap;

#[derive(Debug, serde::Deserialize)]
pub struct Base {
    pub forumlas: Option<HashMap<String, String>>,
    pub properties: Option<HashMap<String, Property>>,
    pub filters: Option<Filter>,
    pub views: Vec<View>,
}

#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Property {
    pub display_name: Option<String>,
}

#[derive(Debug, serde::Deserialize)]
#[serde(untagged)]
pub enum Filter {
    And(AndFilter),
    Not(NotFilter),
    Or(OrFilter),
    Expr(String),
}

#[derive(Debug, serde::Deserialize)]
pub struct AndFilter {
    pub and: Vec<Filter>,
}

#[derive(Debug, serde::Deserialize)]
pub struct NotFilter {
    pub not: Vec<Filter>,
}

#[derive(Debug, serde::Deserialize)]
pub struct OrFilter {
    pub or: Vec<Filter>,
}

#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ViewType {
    Table,
    Cards,
}

#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct View {
    #[serde(rename = "type")]
    pub typ: ViewType,
    pub name: String,
    pub filters: Option<Filter>,
    pub order: Option<Vec<String>>,
    pub limit: Option<usize>,
    pub card_size: Option<usize>,
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    #[ignore]
    fn test() {
        static BASE: &str = r#"properties:
    note.title:
        displayName: Title
    note.author:
        displayName: Author
    note.url:
        displayName: URL
    note.description:
        displayName: Description
views:
    - type: cards
      name: Cards
      filters:
          and:
              - note["link-data"] == "fanfiction"
              - favorite == true
              - not:
                  - favorite == false
      order:
          - title
          - author
          - url
          - description
      limit: 10
      cardSize: 800
"#;

        panic!("{:#?}", serde_yaml::from_str::<Base>(BASE));
    }
}
