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

            
3
use crate::{
4
    Response,
5
    commands::{Command, CommandRequest, CommandResponse, RequestParserError, ResponseParserError},
6
    filter::Filter,
7
    request_tokenizer::RequestTokenizer,
8
    response_tokenizer::ResponseAttributes,
9
    types::{DbSongInfo, Priority, SongId, SongPosition, Sort, WindowRange},
10
};
11

            
12
pub struct PlaylistFind;
13

            
14
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
15
pub struct PlaylistFindRequest {
16
    filter: Filter,
17
    sort: Option<Sort>,
18
    window: Option<WindowRange>,
19
}
20

            
21
impl PlaylistFindRequest {
22
    pub fn new(filter: Filter, sort: Option<Sort>, window: Option<WindowRange>) -> Self {
23
        Self {
24
            filter,
25
            sort,
26
            window,
27
        }
28
    }
29
}
30

            
31
impl CommandRequest for PlaylistFindRequest {
32
    const COMMAND: &'static str = "playlistfind";
33
    const MIN_ARGS: u32 = 1;
34
    const MAX_ARGS: Option<u32> = Some(3);
35

            
36
    fn into_request_enum(self) -> crate::Request {
37
        crate::Request::PlaylistFind(self.filter, self.sort, self.window)
38
    }
39

            
40
    fn from_request_enum(request: crate::Request) -> Option<Self> {
41
        match request {
42
            crate::Request::PlaylistFind(filter, sort, window) => Some(PlaylistFindRequest {
43
                filter,
44
                sort,
45
                window,
46
            }),
47
            _ => None,
48
        }
49
    }
50

            
51
    fn serialize(&self) -> String {
52
        let mut cmd = format!("{} {}", Self::COMMAND, self.filter);
53
        if let Some(sort) = &self.sort {
54
            cmd.push_str(&format!(" sort {}", sort));
55
        }
56
        if let Some(window) = &self.window {
57
            cmd.push_str(&format!(" window {}", window));
58
        }
59
        cmd.push('\n');
60
        cmd
61
    }
62

            
63
    fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
64
        let filter = match parts.next() {
65
            Some(f) => {
66
                Filter::parse(f).map_err(|_| RequestParserError::SyntaxError(1, f.to_owned()))?
67
            }
68
            None => return Err(Self::missing_arguments_error(0)),
69
        };
70

            
71
        let mut argument_index_counter = 0;
72
        let mut sort_or_window = parts.next();
73
        let mut sort = None;
74
        if let Some("sort") = sort_or_window {
75
            argument_index_counter += 1;
76
            let s = parts
77
                .next()
78
                .ok_or(RequestParserError::MissingKeywordValue {
79
                    keyword: "sort",
80
                    argument_index: argument_index_counter,
81
                })?;
82
            sort = Some(
83
                s.parse()
84
                    .map_err(|_| RequestParserError::SubtypeParserError {
85
                        argument_index: argument_index_counter,
86
                        expected_type: "Sort",
87
                        raw_input: s.to_string(),
88
                    })?,
89
            );
90
            sort_or_window = parts.next();
91
        }
92

            
93
        let mut window = None;
94
        if let Some("window") = sort_or_window {
95
            argument_index_counter += 1;
96
            let w = parts
97
                .next()
98
                .ok_or(RequestParserError::MissingKeywordValue {
99
                    keyword: "window",
100
                    argument_index: argument_index_counter,
101
                })?;
102
            window = Some(
103
                w.parse()
104
                    .map_err(|_| RequestParserError::SubtypeParserError {
105
                        argument_index: argument_index_counter,
106
                        expected_type: "WindowRange",
107
                        raw_input: w.to_string(),
108
                    })?,
109
            );
110
        }
111

            
112
        Self::throw_if_too_many_arguments(parts)?;
113

            
114
        Ok(PlaylistFindRequest {
115
            filter,
116
            sort,
117
            window,
118
        })
119
    }
120
}
121

            
122
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
123
pub struct PlaylistFindResponse(Vec<PlaylistFindResponseEntry>);
124

            
125
impl PlaylistFindResponse {
126
    pub fn new(items: Vec<PlaylistFindResponseEntry>) -> Self {
127
        PlaylistFindResponse(items)
128
    }
129
}
130

            
131
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
132
pub struct PlaylistFindResponseEntry {
133
    pub position: SongPosition,
134
    pub id: SongId,
135
    pub priority: Option<Priority>,
136
    pub song_info: DbSongInfo,
137
}
138

            
139
impl PlaylistFindResponseEntry {
140
    pub fn new(
141
        position: SongPosition,
142
        id: SongId,
143
        priority: Option<Priority>,
144
        song_info: DbSongInfo,
145
    ) -> Self {
146
        Self {
147
            position,
148
            id,
149
            priority,
150
            song_info,
151
        }
152
    }
153
}
154

            
155
impl CommandResponse for PlaylistFindResponse {
156
    fn into_response_enum(self) -> Response {
157
        todo!()
158
    }
159

            
160
    fn from_response_enum(_response: Response) -> Option<Self> {
161
        todo!()
162
    }
163

            
164
    fn parse(_parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
165
        unimplemented!()
166
    }
167
}
168

            
169
impl Command for PlaylistFind {
170
    type Request = PlaylistFindRequest;
171
    type Response = PlaylistFindResponse;
172
}