1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//! user's model
use crate::errors::errors::UsersError;
use crate::models::user_id::UserId;

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct User {
    /// User ID
    id: UserId,
    /// Username
    name: Username,
    email: String,
    /// the partners
    /// if there is no partners, this value will be an empty vector.
    partners: Vec<UserId>
}

impl User {
    pub (crate) fn new(id: &UserId, name: &Username, email: &str, partners: Option<&Vec<UserId>>) -> Self {
        Self {
            id: id.to_owned(),
            name: name.to_owned(),
            email: email.to_string(),
            partners: match partners {
                Some(val) => val.to_owned(),
                None => Vec::new()
            }
        }
    }
    
    pub fn id(&self) -> &UserId { 
        &self.id
    }
    
    pub fn name(&self) -> &str {
        &self.name.name
    }
    
    pub fn email(&self) -> &str {
        &self.email
    } 
    
    pub fn partners(&self) -> &Vec<UserId> {
        &self.partners
    }

    // change the username
    pub fn update_name(mut self, name: &Username) -> Self {
        self.name = name.to_owned();
        self
    }

    // add a new partner
    pub fn add_partner(&mut self, partner_id: &UserId) {
        // if the required partner is not existing in the partner, append it.
        if !self.partners.iter().any(|id| id.eq(&partner_id)) {
            self.partners.push(partner_id.to_owned())
        }
    }

    // remove a partner
    pub fn remove_partner(&mut self, partner_id: &UserId) {
        self.partners = self.partners.iter().filter(|id| !id.eq(&partner_id)).cloned().collect::<Vec<UserId>>();
    }
}

/// Username must be grater than 0 and less than equal 255.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Username {
    // must be 0 < name <= 255
    name: String
}

impl Username {
    pub fn name(&self) -> &str {
        &self.name
    }
}

impl TryFrom<&str> for Username {
    type Error = UsersError;

    fn try_from(name: &str) -> Result<Self, UsersError> {
        let name_len = name.len();

        if 255 < name_len {
            Err(UsersError::UsernameError("The name length must be less than 255 characters.".to_string()))
        } else if name_len < 1 {
            Err(UsersError::UsernameError("The name length must be grater than 0.".to_string()))
        } else {
            Ok(Self {
                name: name.to_string()
            })
        }
    }
}

#[cfg(test)]
mod user_test {
    use super::*;

    #[test]
    fn test_change_name() {
        let user = User::new(&UserId::generate(), &Username::try_from("name").unwrap(), "", None);
        let updated = user.update_name(&Username::try_from("name2").unwrap());
        assert_eq!(updated.name.name, "name2");
    }

    #[test]
    fn test_add_a_new_partner() {
        // Arrange
        let user_id = UserId::generate();
        let mut user = User::new(&UserId::generate(), &Username::try_from("name").unwrap(), "", None);

        // Act
        user.add_partner(&user_id);

        // Assert
        assert_eq!(user.partners.len(), 1); // user_id2 is removed
        assert_eq!(user.partners, vec![user_id]);
    }

    #[test]
    fn test_remove_partner() {
        // Arrange
        let user_id = UserId::generate();
        let user_id2 = UserId::generate();
        let partners = vec![user_id.clone(), user_id2.clone()];
        let mut user = User::new(&UserId::generate(), &Username::try_from("name").unwrap(), "", Some(&partners));

        // Act
        user.remove_partner(&user_id2);

        // Assert
        assert_eq!(user.partners.len(), 1); // user_id2 is removed
        assert_eq!(user.partners, vec![user_id]);
    }
}

#[cfg(test)]
mod username_test {
    use super::*;

    #[test]
    fn test_new_name() {
        let name = Username::try_from("name").unwrap().name;
        assert_eq!(name, "name");
    }

    #[test]
    fn test_name_too_short() {
        let name = Username::try_from("");
        assert!(name.is_err());
        assert_eq!(name.unwrap_err().to_string(), "The name length must be grater than 0.".to_string());
    }

    #[test]
    fn test_name_too_long() {
        let name = Username::try_from(vec!["a"; 256].join("").as_str());
        assert!(name.is_err());
        assert_eq!(name.unwrap_err().to_string(), "The name length must be less than 255 characters.".to_string());
    }
}