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

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

            
10
pub struct PlChangesPosId;
11

            
12
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
13
pub struct PlChangesPosIdRequest {
14
    pub version: PlaylistVersion,
15
    pub window: Option<WindowRange>,
16
}
17

            
18
impl PlChangesPosIdRequest {
19
    pub fn new(version: PlaylistVersion, window: Option<WindowRange>) -> Self {
20
        Self { version, window }
21
    }
22
}
23

            
24
impl CommandRequest for PlChangesPosIdRequest {
25
    const COMMAND: &'static str = "plchangesposid";
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::PlChangesPosId(self.version, self.window)
31
    }
32

            
33
    fn from_request_enum(request: crate::Request) -> Option<Self> {
34
        match request {
35
            crate::Request::PlChangesPosId(version, window) => {
36
                Some(PlChangesPosIdRequest { version, window })
37
            }
38
            _ => None,
39
        }
40
    }
41

            
42
    fn serialize(&self) -> String {
43
        match self.window.as_ref() {
44
            Some(window) => format!("{} {} {}\n", Self::COMMAND, self.version, window),
45
            None => format!("{} {}\n", Self::COMMAND, self.version),
46
        }
47
    }
48

            
49
    fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
50
        let version = parts.next().ok_or(Self::missing_arguments_error(0))?;
51
        let version = version
52
            .parse()
53
            .map_err(|_| RequestParserError::SubtypeParserError {
54
                argument_index: 0,
55
                expected_type: "PlaylistVersion",
56
                raw_input: version.to_string(),
57
            })?;
58

            
59
        let window = parts
60
            .next()
61
            .map(|w| {
62
                w.parse()
63
                    .map_err(|_| RequestParserError::SubtypeParserError {
64
                        argument_index: 1,
65
                        expected_type: "WindowRange",
66
                        raw_input: w.to_string(),
67
                    })
68
            })
69
            .transpose()?;
70

            
71
        Self::throw_if_too_many_arguments(parts)?;
72

            
73
        Ok(PlChangesPosIdRequest { version, window })
74
    }
75
}
76

            
77
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
78
pub struct PlChangesPosIdResponse(Vec<PlChangesPosIdResponseEntry>);
79

            
80
impl PlChangesPosIdResponse {
81
    pub fn new(items: Vec<PlChangesPosIdResponseEntry>) -> Self {
82
        PlChangesPosIdResponse(items)
83
    }
84
}
85

            
86
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
87
pub struct PlChangesPosIdResponseEntry {
88
    // 'cpos'
89
    pub position: SongPosition,
90
    pub id: SongId,
91
}
92

            
93
impl PlChangesPosIdResponseEntry {
94
    pub fn new(position: SongPosition, id: SongId) -> Self {
95
        PlChangesPosIdResponseEntry { position, id }
96
    }
97
}
98

            
99
impl CommandResponse for PlChangesPosIdResponse {
100
    fn from_response_enum(_response: crate::Response) -> Option<Self> {
101
        todo!()
102
    }
103

            
104
    fn into_response_enum(self) -> crate::Response {
105
        todo!()
106
    }
107

            
108
    fn parse(_parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
109
        unimplemented!()
110
    }
111
}
112

            
113
impl Command for PlChangesPosId {
114
    type Request = PlChangesPosIdRequest;
115
    type Response = PlChangesPosIdResponse;
116
}