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
163
164
//! All DTOs associated with [`AreaDto`].
// Areas represent shade, hydrology or soil texture.

use chrono::NaiveDate;
use postgis_diesel::types::{Point, Polygon};
use serde::{Deserialize, Serialize};
use typeshare::typeshare;
use utoipa::{IntoParams, ToSchema};
use uuid::Uuid;

use crate::model::r#enum::{
    shade::Shade, soil_texture::SoilTextureEnum, water_requirement::WaterRequirementEnum,
};

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
#[typeshare]
#[serde(tag = "areaKind", content = "area")]
pub enum AreaType {
    Shade(Shade),
    Hydrology(WaterRequirementEnum),
    SoilTexture(SoilTextureEnum),
}

#[typeshare]
#[derive(Debug, Clone, Copy, Serialize, Deserialize, ToSchema, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub enum AreaKind {
    Shade,
    Hydrology,
    SoilTexture,
}

/// Represents area on a map. Areas are for "brushing layers".
#[typeshare]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct AreaDto {
    /// The id of the area.
    pub id: Uuid,
    /// The layer the area is on.
    pub layer_id: Uuid,
    /// The type/strength of area.
    pub area_type: AreaType,
    /// The position of the area on the map.
    ///
    /// E.g. `{"rings": [[{"x": 0.0,"y": 0.0},{"x": 1000.0,"y": 0.0},{"x": 1000.0,"y": 1000.0},{"x": 0.0,"y": 1000.0},{"x": 0.0,"y": 0.0}]],"srid": 4326}`
    #[schema(value_type = Object)]
    pub geometry: Polygon<Point>,
    /// The date the area was added to the map.
    /// If None, the area has always existed.
    pub add_date: Option<NaiveDate>,
    /// The date the area  was removed from the map.
    /// If None, the area is still on the map.
    pub remove_date: Option<NaiveDate>,
    /// Markdown notes.
    pub notes: String,
}

/// Used to create a new area.
#[typeshare]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct NewAreaDto {
    /// The id of the area.
    pub id: Uuid,
    /// The layer the area is on.
    pub layer_id: Uuid,
    /// The type/strength of area.
    pub area_type: AreaType,
    /// The position of the area on the map.
    ///
    /// E.g. `{"rings": [[{"x": 0.0,"y": 0.0},{"x": 1000.0,"y": 0.0},{"x": 1000.0,"y": 1000.0},{"x": 0.0,"y": 1000.0},{"x": 0.0,"y": 0.0}]],"srid": 4326}`
    #[schema(value_type = Object)]
    pub geometry: Polygon<Point>,
    /// The date the area was added to the map.
    /// If None, the area has always existed.
    pub add_date: Option<NaiveDate>,
}

#[typeshare]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(tag = "type", content = "content")]
pub enum AreaUpdate {
    /// Update values of areas according to their type e.g for shades light => permanent.
    UpdateValue(Vec<UpdateAreaValueDto>),
    /// Change the `add_date` of an area.
    UpdateAddDate(Vec<UpdateAddDateAreaDto>),
    /// Change the `remove_date` of an area.
    UpdateRemoveDate(Vec<UpdateRemoveDateAreaDto>),
    /// Change the `notes` of area.
    UpdateNotes(Vec<UpdateNotesAreaDto>),
}

/// Used to differentiate between different update operations on areas.
/// One patch of updates happens on the same area kind.
///
/// Ordering of enum variants is important.
/// Serde will try to deserialize starting from the top.
#[typeshare]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct UpdateAreaDto {
    pub area_kind: AreaKind,
    pub update: AreaUpdate,
}

/// Used to update the values of an existing area.
#[typeshare]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct UpdateAreaValueDto {
    /// The id of the area.
    pub id: Uuid,
    /// The new area_type
    pub area_type: AreaType,
}

/// Used to change the `add_date` of an area.
#[typeshare]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct UpdateAddDateAreaDto {
    /// The id of the area.
    pub id: Uuid,
    /// The date the area was added to the map.
    /// If None, the area has always existed.
    pub add_date: Option<NaiveDate>,
}

/// Used to change the `remove_date` of an area.
#[typeshare]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct UpdateRemoveDateAreaDto {
    /// The id of the shading.
    pub id: Uuid,
    /// The date the shading was removed from the map.
    /// If None, the shading is still on the map.
    pub remove_date: Option<NaiveDate>,
}

/// Used to change the `notes` of an area.
#[typeshare]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct UpdateNotesAreaDto {
    /// The id of the area.
    pub id: Uuid,
    /// Markdown notes.
    pub notes: String,
}

/// Query parameters for searching areas.
#[typeshare]
#[derive(Debug, Deserialize, IntoParams)]
pub struct AreaSearchParameters {
    /// The id of the layer the area is on.
    pub layer_id: Option<Uuid>,
    /// Areas that exist around this date are returned.
    pub relative_to_date: NaiveDate,
    /// The type of area.
    pub kind: AreaKind,
}