1
use std::collections::HashMap;
2

            
3
use serde::{Deserialize, Serialize};
4

            
5
use crate::{
6
    commands::{CommandRequest, CommandResponse, RequestParserError, ResponseParserError},
7
    filter::Filter,
8
    request_tokenizer::RequestTokenizer,
9
    response_tokenizer::{ResponseAttributes, get_and_parse_property},
10
    types::{GroupType, Seconds},
11
};
12

            
13
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14
pub struct SearchCountRequest {
15
    filter: Filter,
16
    group: Option<GroupType>,
17
}
18

            
19
impl SearchCountRequest {
20
    pub fn new(filter: Filter, group: Option<GroupType>) -> Self {
21
        Self { filter, group }
22
    }
23
}
24

            
25
impl CommandRequest for SearchCountRequest {
26
    type Response = SearchCountResponse;
27

            
28
    const COMMAND: &'static str = "searchcount";
29
    const MIN_ARGS: u32 = 1;
30
    const MAX_ARGS: Option<u32> = Some(2);
31

            
32
    fn serialize(&self) -> String {
33
        let mut cmd = format!("{} {}", Self::COMMAND, self.filter);
34
        if let Some(group) = &self.group {
35
            cmd.push_str(&format!(" group {}", group));
36
        }
37
        cmd.push('\n');
38
        cmd
39
    }
40

            
41
    fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
42
        let filter = match parts.next() {
43
            Some(f) => {
44
                Filter::parse(f).map_err(|_| RequestParserError::SyntaxError(1, f.to_owned()))?
45
            }
46
            None => return Err(Self::missing_arguments_error(0)),
47
        };
48

            
49
        let group = if let Some("group") = parts.next() {
50
            let group = parts
51
                .next()
52
                .ok_or(RequestParserError::MissingKeywordValue {
53
                    keyword: "group",
54
                    argument_index: 1,
55
                })?;
56
            Some(
57
                group
58
                    .parse()
59
                    .map_err(|_| RequestParserError::SubtypeParserError {
60
                        argument_index: 1,
61
                        expected_type: "Group",
62
                        raw_input: group.to_string(),
63
                    })?,
64
            )
65
        } else {
66
            None
67
        };
68

            
69
        Self::throw_if_too_many_arguments(parts)?;
70

            
71
        Ok(SearchCountRequest { filter, group })
72
    }
73
}
74

            
75
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
76
pub struct SearchCountResponse {
77
    pub songs: usize,
78
    pub playtime: Seconds,
79
}
80

            
81
impl SearchCountResponse {
82
    pub fn new(songs: usize, playtime: Seconds) -> Self {
83
        Self { songs, playtime }
84
    }
85
}
86

            
87
impl CommandResponse for SearchCountResponse {
88
    type Request = SearchCountRequest;
89

            
90
    fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
91
        let parts: HashMap<_, _> = parts.into_map()?;
92

            
93
        let songs = get_and_parse_property!(parts, "songs", Text);
94
        let playtime = get_and_parse_property!(parts, "playtime", Text);
95

            
96
        Ok(SearchCountResponse { songs, playtime })
97
    }
98

            
99
    fn serialize(&self) -> Vec<u8> {
100
        unimplemented!("response serialization is not yet implemented for SearchCountResponse")
101
    }
102
}