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

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

            
11
pub struct PlaylistFind;
12

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

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

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

            
35
    fn serialize(&self) -> String {
36
        let mut cmd = format!("{} {}", Self::COMMAND, self.filter);
37
        if let Some(sort) = &self.sort {
38
            cmd.push_str(&format!(" sort {}", sort));
39
        }
40
        if let Some(window) = &self.window {
41
            cmd.push_str(&format!(" window {}", window));
42
        }
43
        cmd.push('\n');
44
        cmd
45
    }
46

            
47
    fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
48
        let filter = match parts.next() {
49
            Some(f) => {
50
                Filter::parse(f).map_err(|_| RequestParserError::SyntaxError(1, f.to_owned()))?
51
            }
52
            None => return Err(Self::missing_arguments_error(0)),
53
        };
54

            
55
        let mut argument_index_counter = 0;
56
        let mut sort_or_window = parts.next();
57
        let mut sort = None;
58
        if let Some("sort") = sort_or_window {
59
            argument_index_counter += 1;
60
            let s = parts
61
                .next()
62
                .ok_or(RequestParserError::MissingKeywordValue {
63
                    keyword: "sort",
64
                    argument_index: argument_index_counter,
65
                })?;
66
            sort = Some(
67
                s.parse()
68
                    .map_err(|_| RequestParserError::SubtypeParserError {
69
                        argument_index: argument_index_counter,
70
                        expected_type: "Sort",
71
                        raw_input: s.to_string(),
72
                    })?,
73
            );
74
            sort_or_window = parts.next();
75
        }
76

            
77
        let mut window = None;
78
        if let Some("window") = sort_or_window {
79
            argument_index_counter += 1;
80
            let w = parts
81
                .next()
82
                .ok_or(RequestParserError::MissingKeywordValue {
83
                    keyword: "window",
84
                    argument_index: argument_index_counter,
85
                })?;
86
            window = Some(
87
                w.parse()
88
                    .map_err(|_| RequestParserError::SubtypeParserError {
89
                        argument_index: argument_index_counter,
90
                        expected_type: "WindowRange",
91
                        raw_input: w.to_string(),
92
                    })?,
93
            );
94
        }
95

            
96
        Self::throw_if_too_many_arguments(parts)?;
97

            
98
        Ok(PlaylistFindRequest {
99
            filter,
100
            sort,
101
            window,
102
        })
103
    }
104
}
105

            
106
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
107
pub struct PlaylistFindResponse(Vec<PlaylistFindResponseEntry>);
108

            
109
impl PlaylistFindResponse {
110
    pub fn new(items: Vec<PlaylistFindResponseEntry>) -> Self {
111
        PlaylistFindResponse(items)
112
    }
113
}
114

            
115
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
116
pub struct PlaylistFindResponseEntry {
117
    pub position: SongPosition,
118
    pub id: SongId,
119
    pub priority: Option<Priority>,
120
    pub song_info: DbSongInfo,
121
}
122

            
123
impl PlaylistFindResponseEntry {
124
    pub fn new(
125
        position: SongPosition,
126
        id: SongId,
127
        priority: Option<Priority>,
128
        song_info: DbSongInfo,
129
    ) -> Self {
130
        Self {
131
            position,
132
            id,
133
            priority,
134
            song_info,
135
        }
136
    }
137
}
138

            
139
impl CommandResponse for PlaylistFindResponse {
140
    fn parse(_parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
141
        unimplemented!()
142
    }
143
}
144

            
145
impl Command for PlaylistFind {
146
    type Request = PlaylistFindRequest;
147
    type Response = PlaylistFindResponse;
148
}