use serde::Serialize;

#[derive(Clone, Debug, Serialize)]
#[serde(tag = "event", rename_all = "snake_case")]
pub enum Event {
    Idle { terminal: String, after_ms: u64 },
    Bell { terminal: String },
    CommandDone { terminal: String, code: i32 },
    Exit { terminal: String, code: u32 },
    Title { terminal: String, title: String },
    Activity { terminal: String },
}

impl Event {
    pub fn terminal_id(&self) -> &str {
        match self {
            Self::Idle { terminal, .. }
            | Self::Bell { terminal }
            | Self::CommandDone { terminal, .. }
            | Self::Exit { terminal, .. }
            | Self::Title { terminal, .. }
            | Self::Activity { terminal } => terminal,
        }
    }
}

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

    #[test]
    fn serialize_idle() {
        let e = Event::Idle {
            terminal: "t1".into(),
            after_ms: 100,
        };
        let j: serde_json::Value =
            serde_json::from_str(
                &serde_json::to_string(&e).unwrap(),
            )
            .unwrap();
        assert_eq!(j["event"], "idle");
        assert_eq!(j["terminal"], "t1");
        assert_eq!(j["after_ms"], 100);
    }

    #[test]
    fn serialize_bell() {
        let e = Event::Bell {
            terminal: "t2".into(),
        };
        let j: serde_json::Value =
            serde_json::from_str(
                &serde_json::to_string(&e).unwrap(),
            )
            .unwrap();
        assert_eq!(j["event"], "bell");
        assert_eq!(j["terminal"], "t2");
    }

    #[test]
    fn serialize_command_done() {
        let e = Event::CommandDone {
            terminal: "t1".into(),
            code: 0,
        };
        let j: serde_json::Value =
            serde_json::from_str(
                &serde_json::to_string(&e).unwrap(),
            )
            .unwrap();
        assert_eq!(j["event"], "command_done");
        assert_eq!(j["terminal"], "t1");
        assert_eq!(j["code"], 0);
    }

    #[test]
    fn serialize_exit() {
        let e = Event::Exit {
            terminal: "t1".into(),
            code: 42,
        };
        let j: serde_json::Value =
            serde_json::from_str(
                &serde_json::to_string(&e).unwrap(),
            )
            .unwrap();
        assert_eq!(j["event"], "exit");
        assert_eq!(j["code"], 42);
    }

    #[test]
    fn serialize_activity() {
        let e = Event::Activity {
            terminal: "t3".into(),
        };
        let j: serde_json::Value =
            serde_json::from_str(
                &serde_json::to_string(&e).unwrap(),
            )
            .unwrap();
        assert_eq!(j["event"], "activity");
    }

    #[test]
    fn serialize_title() {
        let e = Event::Title {
            terminal: "t1".into(),
            title: "hi".into(),
        };
        let j: serde_json::Value =
            serde_json::from_str(
                &serde_json::to_string(&e).unwrap(),
            )
            .unwrap();
        assert_eq!(j["event"], "title");
        assert_eq!(j["title"], "hi");
    }
}
