1
use serde::{Deserialize, Serialize};
2

            
3
use crate::{
4
    commands::{Command, CommandRequest, CommandResponse, RequestParserError, ResponseParserError},
5
    request_tokenizer::RequestTokenizer,
6
    response_tokenizer::{ResponseAttributes, get_next_and_parse_property},
7
    types::{SongId, SongPosition, Uri},
8
};
9

            
10
pub struct AddId;
11

            
12
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
13
pub struct AddIdRequest {
14
    pub uri: Uri,
15
    pub position: Option<SongPosition>,
16
}
17

            
18
impl AddIdRequest {
19
    pub fn new(uri: Uri, position: Option<SongPosition>) -> Self {
20
        Self { uri, position }
21
    }
22
}
23

            
24
impl CommandRequest for AddIdRequest {
25
    const COMMAND: &'static str = "addid";
26
    const MIN_ARGS: u32 = 1;
27
    const MAX_ARGS: Option<u32> = Some(2);
28

            
29
    fn into_request_enum(self) -> crate::Request {
30
        crate::Request::AddId(self.uri, self.position)
31
    }
32

            
33
    fn from_request_enum(request: crate::Request) -> Option<Self> {
34
        match request {
35
            crate::Request::AddId(uri, position) => Some(AddIdRequest { uri, position }),
36
            _ => None,
37
        }
38
    }
39

            
40
    fn serialize(&self) -> String {
41
        match self.position {
42
            Some(pos) => format!("{} {} {}\n", Self::COMMAND, self.uri, pos),
43
            None => format!("{} {}\n", Self::COMMAND, self.uri),
44
        }
45
    }
46

            
47
    fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
48
        let uri = match parts.next() {
49
            Some(s) => s,
50
            None => return Err(Self::missing_arguments_error(0)),
51
        };
52

            
53
        let position = match parts.next() {
54
            Some(s) => Some(s.parse::<SongPosition>().map_err(|_| {
55
                RequestParserError::SubtypeParserError {
56
                    argument_index: 1,
57
                    expected_type: "SongPosition",
58
                    raw_input: s.to_owned(),
59
                }
60
            })?),
61
            None => None,
62
        };
63

            
64
        Self::throw_if_too_many_arguments(parts)?;
65

            
66
        Ok(AddIdRequest {
67
            uri: uri.to_string(),
68
            position,
69
        })
70
    }
71
}
72

            
73
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
74
pub struct AddIdResponse {
75
    pub id: SongId,
76
}
77

            
78
impl AddIdResponse {
79
    pub fn new(id: SongId) -> Self {
80
        Self { id }
81
    }
82
}
83

            
84
impl CommandResponse for AddIdResponse {
85
    fn into_response_enum(self) -> crate::Response {
86
        todo!()
87
    }
88

            
89
    fn from_response_enum(_response: crate::Response) -> Option<Self> {
90
        todo!()
91
    }
92

            
93
    fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
94
        let parts: Vec<_> = parts.into();
95
        let mut iter = parts.into_iter();
96
        let (key, id) = get_next_and_parse_property!(iter, Text);
97
        if key != "Id" {
98
            return Err(ResponseParserError::UnexpectedProperty(key.to_string()));
99
        }
100
        Ok(AddIdResponse { id })
101
    }
102
}
103

            
104
impl Command for AddId {
105
    type Request = AddIdRequest;
106
    type Response = AddIdResponse;
107
}