aboutsummaryrefslogtreecommitdiff
path: root/src/dav/caltypes.rs
blob: befecef9c5f77085bb7f5febd7eb7e26da43e5c3 (plain) (blame)
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
#![allow(dead_code)]

use chrono::{DateTime,Utc};
use super::types as dav;
use super::xml;

//@FIXME ACL (rfc3744) is missing, required
//@FIXME Versioning (rfc3253) is missing, required
//@FIXME WebDAV sync (rfc6578) is missing, optional
// For reference, SabreDAV guide gives high-level & real-world overview:
// https://sabre.io/dav/building-a-caldav-client/
// For reference, non-official extensions documented by SabreDAV:
// https://github.com/apple/ccs-calendarserver/tree/master/doc/Extensions


// ----- Root elements -----

// --- (MKCALENDAR PART) ---

/// If a request body is included, it MUST be a CALDAV:mkcalendar XML
/// element.  Instruction processing MUST occur in the order
/// instructions are received (i.e., from top to bottom).
/// Instructions MUST either all be executed or none executed.  Thus,
/// if any error occurs during processing, all executed instructions
/// MUST be undone and a proper error result returned.  Instruction
/// processing details can be found in the definition of the DAV:set
/// instruction in Section 12.13.2 of [RFC2518].
///
/// <!ELEMENT mkcalendar (DAV:set)>
#[derive(Debug, PartialEq)]
pub struct MkCalendar<E: dav::Extension>(pub dav::Set<E>);


/// If a response body for a successful request is included, it MUST
/// be a CALDAV:mkcalendar-response XML element.
///
/// <!ELEMENT mkcalendar-response ANY>
///
/// ----
/// 
/// ANY is not satisfying, so looking at RFC5689
/// https://www.rfc-editor.org/rfc/rfc5689.html#section-5.2
/// 
/// Definition:
///
/// <!ELEMENT mkcol-response (propstat+)>
#[derive(Debug, PartialEq)]
pub struct MkCalendarResponse<E: dav::Extension, N: xml::Node<N>>(pub Vec<dav::PropStat<E,N>>);

// --- (REPORT PART) ---

/// Name:  calendar-query
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  Defines a report for querying calendar object resources.
/// 
/// Description:  See Section 7.8.
/// 
/// Definition:
///
/// <!ELEMENT calendar-query ((DAV:allprop |
///                            DAV:propname |
///                            DAV:prop)?, filter, timezone?)>
#[derive(Debug, PartialEq)]
pub struct CalendarQuery<E: dav::Extension> {
    pub selector: Option<CalendarSelector<E>>,
    pub filter: Filter,
    pub timezone: Option<TimeZone>,
}

///   Name:  calendar-multiget
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  CalDAV report used to retrieve specific calendar object
/// resources.
///
/// Description:  See Section 7.9.
///
/// Definition:
///
/// <!ELEMENT calendar-multiget ((DAV:allprop |
///                               DAV:propname |
///                               DAV:prop)?, DAV:href+)>
#[derive(Debug, PartialEq)]
pub struct CalendarMultiget<E: dav::Extension> {
    pub selector: Option<CalendarSelector<E>>,
    pub href: Vec<dav::Href>,
}

/// Name:  free-busy-query
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  CalDAV report used to generate a VFREEBUSY to determine
/// busy time over a specific time range.
///
/// Description:  See Section 7.10.
///
/// Definition:
/// <!ELEMENT free-busy-query (time-range)>
#[derive(Debug, PartialEq)]
pub struct FreeBusyQuery(pub TimeRange);

// ----- Hooks -----
#[derive(Debug, PartialEq)]
pub enum ResourceType {
    Calendar,
}

/// Check the matching Property object for documentation
#[derive(Debug, PartialEq)]
pub enum PropertyRequest {
    CalendarDescription,
    CalendarTimezone,
    SupportedCalendarComponentSet,
    SupportedCalendarData,
    MaxResourceSize,
    MinDateTime,
    MaxDateTime,
    MaxInstances,
    MaxAttendeesPerInstance,
    SupportedCollationSet,    
    CalendarData(CalendarDataRequest),
}

#[derive(Debug, PartialEq)]
pub enum Property {
    /// Name:  calendar-description
    /// 
    /// Namespace:  urn:ietf:params:xml:ns:caldav
    ///
    /// Purpose:  Provides a human-readable description of the calendar
    /// collection.
    ///
    /// Conformance:  This property MAY be defined on any calendar
    /// collection.  If defined, it MAY be protected and SHOULD NOT be
    /// returned by a PROPFIND DAV:allprop request (as defined in Section
    /// 12.14.1 of [RFC2518]).  An xml:lang attribute indicating the human
    /// language of the description SHOULD be set for this property by
    /// clients or through server provisioning.  Servers MUST return any
    /// xml:lang attribute if set for the property.
    ///
    /// Description:  If present, the property contains a description of the
    /// calendar collection that is suitable for presentation to a user.
    /// If not present, the client should assume no description for the
    /// calendar collection.
    ///
    /// Definition:
    ///
    /// <!ELEMENT calendar-description (#PCDATA)>
    /// PCDATA value: string
    ///
    /// Example:
    ///
    /// <C:calendar-description xml:lang="fr-CA"
    ///     xmlns:C="urn:ietf:params:xml:ns:caldav"
    /// >Calendrier de Mathilde Desruisseaux</C:calendar-description>
    CalendarDescription {
        lang: Option<String>,
        text: String,
    },

    /// 5.2.2.  CALDAV:calendar-timezone Property
    ///
    /// Name:  calendar-timezone
    ///
    /// Namespace:  urn:ietf:params:xml:ns:caldav
    ///
    /// Purpose:  Specifies a time zone on a calendar collection.
    ///
    /// Conformance:  This property SHOULD be defined on all calendar
    /// collections.  If defined, it SHOULD NOT be returned by a PROPFIND
    /// DAV:allprop request (as defined in Section 12.14.1 of [RFC2518]).
    ///
    /// Description:  The CALDAV:calendar-timezone property is used to
    /// specify the time zone the server should rely on to resolve "date"
    /// values and "date with local time" values (i.e., floating time) to
    /// "date with UTC time" values.  The server will require this
    /// information to determine if a calendar component scheduled with
    /// "date" values or "date with local time" values overlaps a CALDAV:
    /// time-range specified in a CALDAV:calendar-query REPORT.  The
    /// server will also require this information to compute the proper
    /// FREEBUSY time period as "date with UTC time" in the VFREEBUSY
    /// component returned in a response to a CALDAV:free-busy-query
    /// REPORT request that takes into account calendar components
    /// scheduled with "date" values or "date with local time" values.  In
    /// the absence of this property, the server MAY rely on the time zone
    /// of their choice.
    ///
    /// Note:  The iCalendar data embedded within the CALDAV:calendar-
    /// timezone XML element MUST follow the standard XML character data
    /// encoding rules, including use of &lt;, &gt;, &amp; etc. entity
    /// encoding or the use of a <![CDATA[ ... ]]> construct.  In the
    /// later case, the iCalendar data cannot contain the character
    /// sequence "]]>", which is the end delimiter for the CDATA section.
    ///
    ///    Definition:
    ///
    /// <!ELEMENT calendar-timezone (#PCDATA)>
    ///     PCDATA value: an iCalendar object with exactly one VTIMEZONE component.
    ///
    /// Example:
    ///
    /// <C:calendar-timezone
    ///     xmlns:C="urn:ietf:params:xml:ns:caldav">BEGIN:VCALENDAR
    /// PRODID:-//Example Corp.//CalDAV Client//EN
    /// VERSION:2.0
    /// BEGIN:VTIMEZONE
    /// TZID:US-Eastern
    /// LAST-MODIFIED:19870101T000000Z
    /// BEGIN:STANDARD
    /// DTSTART:19671029T020000
    /// RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
    /// TZOFFSETFROM:-0400
    /// TZOFFSETTO:-0500
    /// TZNAME:Eastern Standard Time (US &amp; Canada)
    /// END:STANDARD
    /// BEGIN:DAYLIGHT
    /// DTSTART:19870405T020000
    /// RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
    /// TZOFFSETFROM:-0500
    /// TZOFFSETTO:-0400
    /// TZNAME:Eastern Daylight Time (US &amp; Canada)
    /// END:DAYLIGHT
    /// END:VTIMEZONE
    /// END:VCALENDAR
    /// </C:calendar-timezone>
    //@FIXME we might want to put a buffer here or an iCal parsed object
    CalendarTimezone(String),

    /// Name:  supported-calendar-component-set
    ///
    /// Namespace:  urn:ietf:params:xml:ns:caldav
    ///
    /// Purpose:  Specifies the calendar component types (e.g., VEVENT,
    /// VTODO, etc.) that calendar object resources can contain in the
    /// calendar collection.
    ///
    /// Conformance:  This property MAY be defined on any calendar
    /// collection.  If defined, it MUST be protected and SHOULD NOT be
    /// returned by a PROPFIND DAV:allprop request (as defined in Section
    /// 12.14.1 of [RFC2518]).
    ///
    /// Description:  The CALDAV:supported-calendar-component-set property is
    /// used to specify restrictions on the calendar component types that
    /// calendar object resources may contain in a calendar collection.
    /// Any attempt by the client to store calendar object resources with
    /// component types not listed in this property, if it exists, MUST
    /// result in an error, with the CALDAV:supported-calendar-component
    /// precondition (Section 5.3.2.1) being violated.  Since this
    /// property is protected, it cannot be changed by clients using a
    /// PROPPATCH request.  However, clients can initialize the value of
    /// this property when creating a new calendar collection with
    /// MKCALENDAR.  The empty-element tag <C:comp name="VTIMEZONE"/> MUST
    /// only be specified if support for calendar object resources that
    /// only contain VTIMEZONE components is provided or desired.  Support
    /// for VTIMEZONE components in calendar object resources that contain
    /// VEVENT or VTODO components is always assumed.  In the absence of
    /// this property, the server MUST accept all component types, and the
    /// client can assume that all component types are accepted.
    ///
    /// Definition:
    ///
    /// <!ELEMENT supported-calendar-component-set (comp+)>
    ///
    /// Example:
    ///
    /// <C:supported-calendar-component-set
    ///     xmlns:C="urn:ietf:params:xml:ns:caldav">
    ///     <C:comp name="VEVENT"/>
    ///     <C:comp name="VTODO"/>
    /// </C:supported-calendar-component-set>
    SupportedCalendarComponentSet(Vec<CompSupport>),

    ///  Name:  supported-calendar-data
    ///
    /// Namespace:  urn:ietf:params:xml:ns:caldav
    ///
    /// Purpose:  Specifies what media types are allowed for calendar object
    /// resources in a calendar collection.
    ///
    /// Conformance:  This property MAY be defined on any calendar
    /// collection.  If defined, it MUST be protected and SHOULD NOT be
    /// returned by a PROPFIND DAV:allprop request (as defined in Section
    /// 12.14.1 of [RFC2518]).
    ///
    /// Description:  The CALDAV:supported-calendar-data property is used to
    /// specify the media type supported for the calendar object resources
    /// contained in a given calendar collection (e.g., iCalendar version
    /// 2.0).  Any attempt by the client to store calendar object
    /// resources with a media type not listed in this property MUST
    /// result in an error, with the CALDAV:supported-calendar-data
    /// precondition (Section 5.3.2.1) being violated.  In the absence of
    /// this property, the server MUST only accept data with the media
    /// type "text/calendar" and iCalendar version 2.0, and clients can
    /// assume that the server will only accept this data.
    ///
    /// Definition:
    ///
    /// <!ELEMENT supported-calendar-data (calendar-data+)>
    ///
    /// Example:
    ///
    /// <C:supported-calendar-data
    ///     xmlns:C="urn:ietf:params:xml:ns:caldav">
    ///     <C:calendar-data content-type="text/calendar" version="2.0"/>
    /// </C:supported-calendar-data>
    ///
    /// -----
    ///
    /// <!ELEMENT calendar-data EMPTY>
    ///
    /// when nested in the CALDAV:supported-calendar-data property
    /// to specify a supported media type for calendar object
    /// resources;
    SupportedCalendarData(Vec<CalendarDataEmpty>),

    ///  Name:  max-resource-size
    ///
    /// Namespace:  urn:ietf:params:xml:ns:caldav
    ///
    /// Purpose:  Provides a numeric value indicating the maximum size of a
    /// resource in octets that the server is willing to accept when a
    /// calendar object resource is stored in a calendar collection.
    ///
    /// Conformance:  This property MAY be defined on any calendar
    /// collection.  If defined, it MUST be protected and SHOULD NOT be
    /// returned by a PROPFIND DAV:allprop request (as defined in Section
    /// 12.14.1 of [RFC2518]).
    ///
    /// Description:  The CALDAV:max-resource-size is used to specify a
    /// numeric value that represents the maximum size in octets that the
    /// server is willing to accept when a calendar object resource is
    /// stored in a calendar collection.  Any attempt to store a calendar
    /// object resource exceeding this size MUST result in an error, with
    /// the CALDAV:max-resource-size precondition (Section 5.3.2.1) being
    /// violated.  In the absence of this property, the client can assume
    /// that the server will allow storing a resource of any reasonable
    /// size.
    ///
    /// Definition:
    ///
    /// <!ELEMENT max-resource-size (#PCDATA)>
    /// PCDATA value: a numeric value (positive integer)
    ///
    ///    Example:
    ///
    /// <C:max-resource-size xmlns:C="urn:ietf:params:xml:ns:caldav">
    /// 102400
    /// </C:max-resource-size>
    MaxResourceSize(u64),

    /// CALDAV:min-date-time Property
    ///
    /// Name:  min-date-time
    ///
    /// Namespace:  urn:ietf:params:xml:ns:caldav
    ///
    /// Purpose:  Provides a DATE-TIME value indicating the earliest date and
    /// time (in UTC) that the server is willing to accept for any DATE or
    /// DATE-TIME value in a calendar object resource stored in a calendar
    /// collection.
    ///
    /// Conformance:  This property MAY be defined on any calendar
    /// collection.  If defined, it MUST be protected and SHOULD NOT be
    /// returned by a PROPFIND DAV:allprop request (as defined in Section
    /// 12.14.1 of [RFC2518]).
    ///
    /// Description:  The CALDAV:min-date-time is used to specify an
    /// iCalendar DATE-TIME value in UTC that indicates the earliest
    /// inclusive date that the server is willing to accept for any
    /// explicit DATE or DATE-TIME value in a calendar object resource
    /// stored in a calendar collection.  Any attempt to store a calendar
    /// object resource using a DATE or DATE-TIME value earlier than this
    /// value MUST result in an error, with the CALDAV:min-date-time
    /// precondition (Section 5.3.2.1) being violated.  Note that servers
    /// MUST accept recurring components that specify instances beyond
    /// this limit, provided none of those instances have been overridden.
    /// In that case, the server MAY simply ignore those instances outside
    /// of the acceptable range when processing reports on the calendar
    /// object resource.  In the absence of this property, the client can
    /// assume any valid iCalendar date may be used at least up to the
    /// CALDAV:max-date-time value, if that is defined.
    ///
    /// Definition:
    ///
    /// <!ELEMENT min-date-time (#PCDATA)>
    /// PCDATA value: an iCalendar format DATE-TIME value in UTC
    ///
    /// Example:
    ///
    /// <C:min-date-time xmlns:C="urn:ietf:params:xml:ns:caldav">
    /// 19000101T000000Z
    /// </C:min-date-time>
    MinDateTime(DateTime<Utc>),

    /// CALDAV:max-date-time Property
    ///
    /// Name:  max-date-time
    ///
    /// Namespace:  urn:ietf:params:xml:ns:caldav
    ///
    /// Purpose:  Provides a DATE-TIME value indicating the latest date and
    /// time (in UTC) that the server is willing to accept for any DATE or
    /// DATE-TIME value in a calendar object resource stored in a calendar
    /// collection.
    ///
    /// Conformance:  This property MAY be defined on any calendar
    /// collection.  If defined, it MUST be protected and SHOULD NOT be
    /// returned by a PROPFIND DAV:allprop request (as defined in Section
    /// 12.14.1 of [RFC2518]).
    ///
    /// Description:  The CALDAV:max-date-time is used to specify an
    /// iCalendar DATE-TIME value in UTC that indicates the inclusive
    /// latest date that the server is willing to accept for any date or
    /// time value in a calendar object resource stored in a calendar
    /// collection.  Any attempt to store a calendar object resource using
    /// a DATE or DATE-TIME value later than this value MUST result in an
    /// error, with the CALDAV:max-date-time precondition
    /// (Section 5.3.2.1) being violated.  Note that servers MUST accept
    /// recurring components that specify instances beyond this limit,
    /// provided none of those instances have been overridden.  In that
    /// case, the server MAY simply ignore those instances outside of the
    /// acceptable range when processing reports on the calendar object
    /// resource.  In the absence of this property, the client can assume
    /// any valid iCalendar date may be used at least down to the CALDAV:
    /// min-date-time value, if that is defined.
    ///
    /// Definition:
    ///
    /// <!ELEMENT max-date-time (#PCDATA)>
    /// PCDATA value: an iCalendar format DATE-TIME value in UTC
    ///
    /// Example:
    ///
    /// <C:max-date-time xmlns:C="urn:ietf:params:xml:ns:caldav">
    /// 20491231T235959Z
    /// </C:max-date-time>
    MaxDateTime(DateTime<Utc>),

    /// CALDAV:max-instances Property
    ///
    /// Name:  max-instances
    ///
    /// Namespace:  urn:ietf:params:xml:ns:caldav
    ///
    /// Purpose:  Provides a numeric value indicating the maximum number of
    /// recurrence instances that a calendar object resource stored in a
    /// calendar collection can generate.
    ///
    /// Conformance:  This property MAY be defined on any calendar
    /// collection.  If defined, it MUST be protected and SHOULD NOT be
    /// returned by a PROPFIND DAV:allprop request (as defined in Section
    /// 12.14.1 of [RFC2518]).
    ///
    /// Description:  The CALDAV:max-instances is used to specify a numeric
    /// value that indicates the maximum number of recurrence instances
    /// that a calendar object resource stored in a calendar collection
    /// can generate.  Any attempt to store a calendar object resource
    /// with a recurrence pattern that generates more instances than this
    /// value MUST result in an error, with the CALDAV:max-instances
    /// precondition (Section 5.3.2.1) being violated.  In the absence of
    /// this property, the client can assume that the server has no limits
    /// on the number of recurrence instances it can handle or expand.
    ///
    /// Definition:
    ///
    /// <!ELEMENT max-instances (#PCDATA)>
    /// PCDATA value: a numeric value (integer greater than zero)
    ///
    /// Example:
    ///
    /// <C:max-instances xmlns:C="urn:ietf:params:xml:ns:caldav">
    /// 100
    /// </C:max-instances>
    MaxInstances(u64),

    ///  CALDAV:max-attendees-per-instance Property
    ///
    /// Name:  max-attendees-per-instance
    ///
    /// Namespace:  urn:ietf:params:xml:ns:caldav
    ///
    /// Purpose:  Provides a numeric value indicating the maximum number of
    /// ATTENDEE properties in any instance of a calendar object resource
    /// stored in a calendar collection.
    ///
    /// Conformance:  This property MAY be defined on any calendar
    /// collection.  If defined, it MUST be protected and SHOULD NOT be
    /// returned by a PROPFIND DAV:allprop request (as defined in Section
    /// 12.14.1 of [RFC2518]).
    ///
    /// Description:  The CALDAV:max-attendees-per-instance is used to
    /// specify a numeric value that indicates the maximum number of
    /// iCalendar ATTENDEE properties on any one instance of a calendar
    /// object resource stored in a calendar collection.  Any attempt to
    /// store a calendar object resource with more ATTENDEE properties per
    /// instance than this value MUST result in an error, with the CALDAV:
    /// max-attendees-per-instance precondition (Section 5.3.2.1) being
    /// violated.  In the absence of this property, the client can assume
    /// that the server can handle any number of ATTENDEE properties in a
    /// calendar component.
    ///
    /// Definition:
    ///
    /// <!ELEMENT max-attendees-per-instance (#PCDATA)>
    /// PCDATA value: a numeric value (integer greater than zero)
    ///
    /// Example:
    ///
    /// <C:max-attendees-per-instance
    ///     xmlns:C="urn:ietf:params:xml:ns:caldav">
    /// 25
    /// </C:max-attendees-per-instance>
    MaxAttendeesPerInstance(u64),

    ///  Name:  supported-collation-set
    ///
    /// Namespace:  urn:ietf:params:xml:ns:caldav
    ///
    /// Purpose:  Identifies the set of collations supported by the server
    /// for text matching operations.
    ///
    /// Conformance:  This property MUST be defined on any resource that
    /// supports a report that does text matching.  If defined, it MUST be
    /// protected and SHOULD NOT be returned by a PROPFIND DAV:allprop
    /// request (as defined in Section 12.14.1 of [RFC2518]).
    ///
    /// Description:  The CALDAV:supported-collation-set property contains
    /// zero or more CALDAV:supported-collation elements, which specify
    /// the collection identifiers of the collations supported by the
    /// server.
    ///
    /// Definition:
    ///
    /// <!ELEMENT supported-collation-set (supported-collation*)>
    /// <!ELEMENT supported-collation (#PCDATA)>
    ///
    /// Example:
    ///
    /// <C:supported-collation-set
    ///     xmlns:C="urn:ietf:params:xml:ns:caldav">
    ///   <C:supported-collation>i;ascii-casemap</C:supported-collation>
    ///   <C:supported-collation>i;octet</C:supported-collation>
    /// </C:supported-collation-set>
    SupportedCollationSet(Vec<SupportedCollation>),

    /// Name:  calendar-data
    ///
    /// Namespace:  urn:ietf:params:xml:ns:caldav
    ///
    /// Purpose:  Specified one of the following:
    ///
    /// 1.  A supported media type for calendar object resources when
    ///     nested in the CALDAV:supported-calendar-data property;
    ///
    /// 2.  The parts of a calendar object resource should be returned by
    ///     a calendaring report;
    ///
    /// 3.  The content of a calendar object resource in a response to a
    ///     calendaring report.
    ///
    /// Description:  When nested in the CALDAV:supported-calendar-data
    /// property, the CALDAV:calendar-data XML element specifies a media
    /// type supported by the CalDAV server for calendar object resources.
    ///
    /// When used in a calendaring REPORT request, the CALDAV:calendar-
    /// data XML element specifies which parts of calendar object
    /// resources need to be returned in the response.  If the CALDAV:
    /// calendar-data XML element doesn't contain any CALDAV:comp element,
    /// calendar object resources will be returned in their entirety.
    ///
    /// Finally, when used in a calendaring REPORT response, the CALDAV:
    /// calendar-data XML element specifies the content of a calendar
    /// object resource.  Given that XML parsers normalize the two-
    /// character sequence CRLF (US-ASCII decimal 13 and US-ASCII decimal
    /// 10) to a single LF character (US-ASCII decimal 10), the CR
    /// character (US-ASCII decimal 13) MAY be omitted in calendar object
    /// resources specified in the CALDAV:calendar-data XML element.
    /// Furthermore, calendar object resources specified in the CALDAV:
    /// calendar-data XML element MAY be invalid per their media type
    /// specification if the CALDAV:calendar-data XML element part of the
    /// calendaring REPORT request did not specify required properties
    /// (e.g., UID, DTSTAMP, etc.), or specified a CALDAV:prop XML element
    /// with the "novalue" attribute set to "yes".
    ///
    /// Note:  The CALDAV:calendar-data XML element is specified in requests
    /// and responses inside the DAV:prop XML element as if it were a
    /// WebDAV property.  However, the CALDAV:calendar-data XML element is
    /// not a WebDAV property and, as such, is not returned in PROPFIND
    /// responses, nor used in PROPPATCH requests.
    /// 
    /// Note:  The iCalendar data embedded within the CALDAV:calendar-data
    /// XML element MUST follow the standard XML character data encoding
    /// rules, including use of &lt;, &gt;, &amp; etc. entity encoding or
    /// the use of a <![CDATA[ ... ]]> construct.  In the later case, the
    /// iCalendar data cannot contain the character sequence "]]>", which
    /// is the end delimiter for the CDATA section.
    CalendarData(CalendarDataPayload),
}

#[derive(Debug, PartialEq)]
pub enum Violation {
    /// (DAV:resource-must-be-null): A resource MUST NOT exist at the
    /// Request-URI;
    ResourceMustBeNull,

    /// (CALDAV:calendar-collection-location-ok): The Request-URI MUST
    /// identify a location where a calendar collection can be created;
    CalendarCollectionLocationOk,
    
    /// (CALDAV:valid-calendar-data): The time zone specified in CALDAV:
    /// calendar-timezone property MUST be a valid iCalendar object
    /// containing a single valid VTIMEZONE component.
    ValidCalendarData,

    ///@FIXME should not be here but in RFC3744
    /// !!! ERRATA 1002 !!!
    /// (DAV:need-privileges): The DAV:bind privilege MUST be granted to
    /// the current user on the parent collection of the Request-URI.
    NeedPrivileges,

    ///  (CALDAV:initialize-calendar-collection): A new calendar collection
    /// exists at the Request-URI.  The DAV:resourcetype of the calendar
    /// collection MUST contain both DAV:collection and CALDAV:calendar
    /// XML elements.
    InitializeCalendarCollection,

    /// (CALDAV:supported-calendar-data): The resource submitted in the
    /// PUT request, or targeted by a COPY or MOVE request, MUST be a
    /// supported media type (i.e., iCalendar) for calendar object
    /// resources;
    SupportedCalendarData,

    /// (CALDAV:valid-calendar-object-resource): The resource submitted in
    /// the PUT request, or targeted by a COPY or MOVE request, MUST obey
    /// all restrictions specified in Section 4.1 (e.g., calendar object
    /// resources MUST NOT contain more than one type of calendar
    /// component, calendar object resources MUST NOT specify the
    /// iCalendar METHOD property, etc.);
    ValidCalendarObjectResource,

    /// (CALDAV:supported-calendar-component): The resource submitted in
    /// the PUT request, or targeted by a COPY or MOVE request, MUST
    /// contain a type of calendar component that is supported in the
    /// targeted calendar collection;
    SupportedCalendarComponent,

    /// (CALDAV:no-uid-conflict): The resource submitted in the PUT
    /// request, or targeted by a COPY or MOVE request, MUST NOT specify
    /// an iCalendar UID property value already in use in the targeted
    /// calendar collection or overwrite an existing calendar object
    /// resource with one that has a different UID property value.
    /// Servers SHOULD report the URL of the resource that is already
    /// making use of the same UID property value in the DAV:href element;
    ///
    /// <!ELEMENT no-uid-conflict (DAV:href)>
    NoUidConflict(dav::Href),

    /// (CALDAV:max-resource-size): The resource submitted in the PUT
    /// request, or targeted by a COPY or MOVE request, MUST have an octet
    /// size less than or equal to the value of the CALDAV:max-resource-
    /// size property value (Section 5.2.5) on the calendar collection
    /// where the resource will be stored;
    MaxResourceSize,

    /// (CALDAV:min-date-time): The resource submitted in the PUT request,
    /// or targeted by a COPY or MOVE request, MUST have all of its
    /// iCalendar DATE or DATE-TIME property values (for each recurring
    /// instance) greater than or equal to the value of the CALDAV:min-
    /// date-time property value (Section 5.2.6) on the calendar
    /// collection where the resource will be stored;
    MinDateTime,
    
    /// (CALDAV:max-date-time): The resource submitted in the PUT request,
    /// or targeted by a COPY or MOVE request, MUST have all of its
    /// iCalendar DATE or DATE-TIME property values (for each recurring
    /// instance) less than the value of the CALDAV:max-date-time property
    /// value (Section 5.2.7) on the calendar collection where the
    /// resource will be stored;
    MaxDateTime,

    /// (CALDAV:max-instances): The resource submitted in the PUT request,
    /// or targeted by a COPY or MOVE request, MUST generate a number of
    /// recurring instances less than or equal to the value of the CALDAV:
    /// max-instances property value (Section 5.2.8) on the calendar
    /// collection where the resource will be stored;
    MaxInstances,

    /// (CALDAV:max-attendees-per-instance): The resource submitted in the
    /// PUT request, or targeted by a COPY or MOVE request, MUST have a
    /// number of ATTENDEE properties on any one instance less than or
    /// equal to the value of the CALDAV:max-attendees-per-instance
    /// property value (Section 5.2.9) on the calendar collection where
    /// the resource will be stored;
    MaxAttendeesPerInstance,

    /// (CALDAV:valid-filter): The CALDAV:filter XML element (see
    /// Section 9.7) specified in the REPORT request MUST be valid.  For
    /// instance, a CALDAV:filter cannot nest a <C:comp name="VEVENT">
    /// element in a <C:comp name="VTODO"> element, and a CALDAV:filter
    /// cannot nest a <C:time-range start="..." end="..."> element in a
    /// <C:prop name="SUMMARY"> element.
    ValidFilter,

    /// (CALDAV:supported-filter): The CALDAV:comp-filter (see
    /// Section 9.7.1), CALDAV:prop-filter (see Section 9.7.2), and
    /// CALDAV:param-filter (see Section 9.7.3) XML elements used in the
    /// CALDAV:filter XML element (see Section 9.7) in the REPORT request
    /// only make reference to components, properties, and parameters for
    /// which queries are supported by the server, i.e., if the CALDAV:
    /// filter element attempts to reference an unsupported component,
    /// property, or parameter, this precondition is violated.  Servers
    /// SHOULD report the CALDAV:comp-filter, CALDAV:prop-filter, or
    /// CALDAV:param-filter for which it does not provide support.
    ///
    /// <!ELEMENT supported-filter (comp-filter*,
    ///                             prop-filter*,
    ///                             param-filter*)>
    SupportedFilter {
        comp: Vec<CompFilter>,
        prop: Vec<PropFilter>,
        param: Vec<ParamFilter>,
    },

    /// (DAV:number-of-matches-within-limits): The number of matching
    /// calendar object resources must fall within server-specific,
    /// predefined limits.  For example, this condition might be triggered
    /// if a search specification would cause the return of an extremely
    /// large number of responses.
    NumberOfMatchesWithinLimits,
}

// -------- Inner XML elements ---------

/// Some of the reports defined in this section do text matches of
/// character strings provided by the client and are compared to stored
/// calendar data.  Since iCalendar data is, by default, encoded in the
/// UTF-8 charset and may include characters outside the US-ASCII charset
/// range in some property and parameter values, there is a need to
/// ensure that text matching follows well-defined rules.
///
/// To deal with this, this specification makes use of the IANA Collation
/// Registry defined in [RFC4790] to specify collations that may be used
/// to carry out the text comparison operations with a well-defined rule.
/// 
/// The comparisons used in CalDAV are all "substring" matches, as per
/// [RFC4790], Section 4.2.  Collations supported by the server MUST
/// support "substring" match operations.
/// 
/// CalDAV servers are REQUIRED to support the "i;ascii-casemap" and
/// "i;octet" collations, as described in [RFC4790], and MAY support
/// other collations.
/// 
/// Servers MUST advertise the set of collations that they support via
/// the CALDAV:supported-collation-set property defined on any resource
/// that supports reports that use collations.
///
/// Clients MUST only use collations from the list advertised by the
/// server.
///
/// In the absence of a collation explicitly specified by the client, or
/// if the client specifies the "default" collation identifier (as
/// defined in [RFC4790], Section 3.1), the server MUST default to using
/// "i;ascii-casemap" as the collation.
///
/// Wildcards (as defined in [RFC4790], Section 3.2) MUST NOT be used in
/// the collation identifier.
/// 
/// If the client chooses a collation not supported by the server, the
/// server MUST respond with a CALDAV:supported-collation precondition
/// error response.
#[derive(Debug, PartialEq)]
pub struct SupportedCollation(pub Collation);

/// <!ELEMENT calendar-data (#PCDATA)>
/// PCDATA value: iCalendar object
///
/// when nested in the DAV:prop XML element in a calendaring
/// REPORT response to specify the content of a returned
/// calendar object resource.
#[derive(Debug, PartialEq)]
pub struct CalendarDataPayload {
    pub mime: Option<CalendarDataSupport>,
    pub payload: String,
}

/// <!ELEMENT calendar-data (comp?,
///                          (expand | limit-recurrence-set)?,
///                          limit-freebusy-set?)>
///
/// when nested in the DAV:prop XML element in a calendaring
/// REPORT request to specify which parts of calendar object
/// resources should be returned in the response;
#[derive(Debug, PartialEq)]
pub struct CalendarDataRequest {
    pub mime: Option<CalendarDataSupport>,
    pub comp: Option<Comp>,
    pub recurrence: Option<RecurrenceModifier>,
    pub limit_freebusy_set: Option<LimitFreebusySet>,
}

/// calendar-data specialization for Property
///
/// <!ELEMENT calendar-data EMPTY>
///
/// when nested in the CALDAV:supported-calendar-data property
/// to specify a supported media type for calendar object
/// resources;
#[derive(Debug, PartialEq)]
pub struct CalendarDataEmpty(pub Option<CalendarDataSupport>);

/// <!ATTLIST calendar-data content-type CDATA "text/calendar"
///                         version CDATA "2.0">
/// content-type value: a MIME media type
/// version value: a version string
/// attributes can be used on all three variants of the
/// CALDAV:calendar-data XML element.
#[derive(Debug, PartialEq)]
pub struct CalendarDataSupport {
    pub content_type: String,
    pub version: String,
}

/// Name:  comp
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  Defines which component types to return.
///
/// Description:  The name value is a calendar component name (e.g.,
/// VEVENT).
///
/// Definition:
///
/// <!ELEMENT comp ((allprop | prop*), (allcomp | comp*))>
/// <!ATTLIST comp name CDATA #REQUIRED>
/// name value: a calendar component name
///
/// Note:  The CALDAV:prop and CALDAV:allprop elements have the same name
/// as the DAV:prop and DAV:allprop elements defined in [RFC2518].
/// However, the CALDAV:prop and CALDAV:allprop elements are defined
/// in the "urn:ietf:params:xml:ns:caldav" namespace instead of the
/// "DAV:" namespace.
#[derive(Debug, PartialEq)]
pub struct Comp {
    pub name: Component,
    pub additional_rules: Option<CompInner>,
}

#[derive(Debug, PartialEq)]
pub struct CompInner {
    pub prop_kind: PropKind,
    pub comp_kind: CompKind,
}

/// For SupportedCalendarComponentSet
///
/// Definition:
///
/// <!ELEMENT supported-calendar-component-set (comp+)>
///
/// Example:
///
/// <C:supported-calendar-component-set
///     xmlns:C="urn:ietf:params:xml:ns:caldav">
///     <C:comp name="VEVENT"/>
///     <C:comp name="VTODO"/>
/// </C:supported-calendar-component-set>
#[derive(Debug, PartialEq)]
pub struct CompSupport(pub Component);

/// Name:  allcomp
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  Specifies that all components shall be returned.
///
/// Description:  The CALDAV:allcomp XML element can be used when the
/// client wants all types of components returned by a calendaring
/// REPORT request.
/// 
/// Definition:
///
/// <!ELEMENT allcomp EMPTY>
#[derive(Debug, PartialEq)]
pub enum CompKind {
    AllComp,
    Comp(Vec<Comp>),
}

/// Name:  allprop
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  Specifies that all properties shall be returned.
///
/// Description:  The CALDAV:allprop XML element can be used when the
/// client wants all properties of components returned by a
/// calendaring REPORT request.
///
/// Definition:
///
/// <!ELEMENT allprop EMPTY>
///
/// Note:  The CALDAV:allprop element has the same name as the DAV:
/// allprop element defined in [RFC2518].  However, the CALDAV:allprop
/// element is defined in the "urn:ietf:params:xml:ns:caldav"
/// namespace instead of the "DAV:" namespace.
#[derive(Debug, PartialEq)]
pub enum PropKind {
    AllProp,
    Prop(Vec<CalProp>),
}

/// Name:  prop
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  Defines which properties to return in the response.
///
/// Description:  The "name" attribute specifies the name of the calendar
/// property to return (e.g., ATTENDEE).  The "novalue" attribute can
/// be used by clients to request that the actual value of the
/// property not be returned (if the "novalue" attribute is set to
/// "yes").  In that case, the server will return just the iCalendar
/// property name and any iCalendar parameters and a trailing ":"
/// without the subsequent value data.
///
/// Definition:
/// <!ELEMENT prop EMPTY>
/// <!ATTLIST prop name CDATA #REQUIRED novalue (yes | no) "no">
/// name value: a calendar property name
/// novalue value: "yes" or "no"
///
/// Note:  The CALDAV:prop element has the same name as the DAV:prop
/// element defined in [RFC2518].  However, the CALDAV:prop element is
/// defined in the "urn:ietf:params:xml:ns:caldav" namespace instead
/// of the "DAV:" namespace.
#[derive(Debug, PartialEq)]
pub struct CalProp {
    pub name: ComponentProperty,
    pub novalue: Option<bool>,
}

#[derive(Debug, PartialEq)]
pub enum RecurrenceModifier {
    Expand(Expand),
    LimitRecurrenceSet(LimitRecurrenceSet),
}

/// Name:  expand
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  Forces the server to expand recurring components into
/// individual recurrence instances.
///
/// Description:  The CALDAV:expand XML element specifies that for a
/// given calendaring REPORT request, the server MUST expand the
/// recurrence set into calendar components that define exactly one
/// recurrence instance, and MUST return only those whose scheduled
/// time intersect a specified time range.
/// 
/// The "start" attribute specifies the inclusive start of the time
/// range, and the "end" attribute specifies the non-inclusive end of
/// the time range.  Both attributes are specified as date with UTC
/// time value.  The value of the "end" attribute MUST be greater than
/// the value of the "start" attribute.
///
/// The server MUST use the same logic as defined for CALDAV:time-
/// range to determine if a recurrence instance intersects the
/// specified time range.
///
/// Recurring components, other than the initial instance, MUST
/// include a RECURRENCE-ID property indicating which instance they
/// refer to.
///
/// The returned calendar components MUST NOT use recurrence
/// properties (i.e., EXDATE, EXRULE, RDATE, and RRULE) and MUST NOT
/// have reference to or include VTIMEZONE components.  Date and local
/// time with reference to time zone information MUST be converted
/// into date with UTC time.
///
/// Definition:
///
/// <!ELEMENT expand EMPTY>
/// <!ATTLIST expand start CDATA #REQUIRED
///                  end   CDATA #REQUIRED>
/// start value: an iCalendar "date with UTC time"
/// end value: an iCalendar "date with UTC time"
#[derive(Debug, PartialEq)]
pub struct Expand(pub DateTime<Utc>, pub DateTime<Utc>);

/// CALDAV:limit-recurrence-set XML Element
///
/// Name:  limit-recurrence-set
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  Specifies a time range to limit the set of "overridden
/// components" returned by the server.
///
/// Description:  The CALDAV:limit-recurrence-set XML element specifies
/// that for a given calendaring REPORT request, the server MUST
/// return, in addition to the "master component", only the
/// "overridden components" that impact a specified time range.  An
/// overridden component impacts a time range if its current start and
/// end times overlap the time range, or if the original start and end
/// times -- the ones that would have been used if the instance were
/// not overridden -- overlap the time range.
///
/// The "start" attribute specifies the inclusive start of the time
/// range, and the "end" attribute specifies the non-inclusive end of
/// the time range.  Both attributes are specified as date with UTC
/// time value.  The value of the "end" attribute MUST be greater than
/// the value of the "start" attribute.
///
/// The server MUST use the same logic as defined for CALDAV:time-
/// range to determine if the current or original scheduled time of an
/// "overridden" recurrence instance intersects the specified time
/// range.
///
/// Overridden components that have a RANGE parameter on their
/// RECURRENCE-ID property may specify one or more instances in the
/// recurrence set, and some of those instances may fall within the
/// specified time range or may have originally fallen within the
/// specified time range prior to being overridden.  If that is the
/// case, the overridden component MUST be included in the results, as
/// it has a direct impact on the interpretation of instances within
/// the specified time range.
///
/// Definition:
///
/// <!ELEMENT limit-recurrence-set EMPTY>
/// <!ATTLIST limit-recurrence-set start CDATA #REQUIRED
///                                end   CDATA #REQUIRED>
/// start value: an iCalendar "date with UTC time"
/// end value: an iCalendar "date with UTC time"
#[derive(Debug, PartialEq)]
pub struct LimitRecurrenceSet(pub DateTime<Utc>, pub DateTime<Utc>);

/// Name:  limit-freebusy-set
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  Specifies a time range to limit the set of FREEBUSY values
/// returned by the server.
///
/// Description:  The CALDAV:limit-freebusy-set XML element specifies
/// that for a given calendaring REPORT request, the server MUST only
/// return the FREEBUSY property values of a VFREEBUSY component that
/// intersects a specified time range.
///
/// The "start" attribute specifies the inclusive start of the time
/// range, and the "end" attribute specifies the non-inclusive end of
/// the time range.  Both attributes are specified as "date with UTC
/// time" value.  The value of the "end" attribute MUST be greater
/// than the value of the "start" attribute.
///
/// The server MUST use the same logic as defined for CALDAV:time-
/// range to determine if a FREEBUSY property value intersects the
/// specified time range.
///
/// Definition:
/// <!ELEMENT limit-freebusy-set EMPTY>
/// <!ATTLIST limit-freebusy-set start CDATA #REQUIRED
///                              end   CDATA #REQUIRED>
/// start value: an iCalendar "date with UTC time"
/// end value: an iCalendar "date with UTC time"
#[derive(Debug, PartialEq)]
pub struct LimitFreebusySet(pub DateTime<Utc>, pub DateTime<Utc>);

/// Used by CalendarQuery & CalendarMultiget
#[derive(Debug, PartialEq)]
pub enum CalendarSelector<E: dav::Extension> {
    AllProp,
    PropName,
    Prop(dav::PropName<E>),
}

/// Name:  comp-filter
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  Specifies search criteria on calendar components.
///
/// Description:  The CALDAV:comp-filter XML element specifies a query
/// targeted at the calendar object (i.e., VCALENDAR) or at a specific
/// calendar component type (e.g., VEVENT).  The scope of the
/// CALDAV:comp-filter XML element is the calendar object when used as
/// a child of the CALDAV:filter XML element.  The scope of the
/// CALDAV:comp-filter XML element is the enclosing calendar component
/// when used as a child of another CALDAV:comp-filter XML element.  A
/// CALDAV:comp-filter is said to match if:
///
///   *  The CALDAV:comp-filter XML element is empty and the calendar
///      object or calendar component type specified by the "name"
///      attribute exists in the current scope;
///
///   or:
///
///   *  The CALDAV:comp-filter XML element contains a CALDAV:is-not-
///      defined XML element and the calendar object or calendar
///      component type specified by the "name" attribute does not exist
///      in the current scope;
///
///   or:
///
///   *  The CALDAV:comp-filter XML element contains a CALDAV:time-range
///      XML element and at least one recurrence instance in the
///      targeted calendar component is scheduled to overlap the
///      specified time range, and all specified CALDAV:prop-filter and
///      CALDAV:comp-filter child XML elements also match the targeted
///      calendar component;
///
///   or:
///
///   *  The CALDAV:comp-filter XML element only contains CALDAV:prop-
///      filter and CALDAV:comp-filter child XML elements that all match
///      the targeted calendar component.
///
/// Definition:
/// <!ELEMENT comp-filter (is-not-defined | (time-range?,
///                        prop-filter*, comp-filter*))>
///
///      <!ATTLIST comp-filter name CDATA #REQUIRED>
///      name value: a calendar object or calendar component
///                  type (e.g., VEVENT)
#[derive(Debug, PartialEq)]
pub struct CompFilter {
    pub name: Component,
    // Option 1 = None, Option 2, 3, 4 = Some
    pub additional_rules: Option<CompFilterRules>,
}
#[derive(Debug, PartialEq)]
pub enum CompFilterRules {
    // Option 2
    IsNotDefined,
    // Options 3 & 4
    Matches(CompFilterMatch),
}
#[derive(Debug, PartialEq)]
pub struct CompFilterMatch {
    pub time_range: Option<TimeRange>,
    pub prop_filter: Vec<PropFilter>,
    pub comp_filter: Vec<CompFilter>,
}

/// Name:  prop-filter
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
/// 
/// Purpose:  Specifies search criteria on calendar properties.
///
/// Description:  The CALDAV:prop-filter XML element specifies a query
/// targeted at a specific calendar property (e.g., CATEGORIES) in the
/// scope of the enclosing calendar component.  A calendar property is
/// said to match a CALDAV:prop-filter if:
///
///   *  The CALDAV:prop-filter XML element is empty and a property of
///      the type specified by the "name" attribute exists in the
///      enclosing calendar component;
///
///   or:
///
///   *  The CALDAV:prop-filter XML element contains a CALDAV:is-not-
///      defined XML element and no property of the type specified by
///      the "name" attribute exists in the enclosing calendar
///      component;
///
///   or:
///
///   *  The CALDAV:prop-filter XML element contains a CALDAV:time-range
///      XML element and the property value overlaps the specified time
///      range, and all specified CALDAV:param-filter child XML elements
///      also match the targeted property;
///
///   or:
///
///   *  The CALDAV:prop-filter XML element contains a CALDAV:text-match
///      XML element and the property value matches it, and all
///      specified CALDAV:param-filter child XML elements also match the
///      targeted property;
///
/// Definition:
///
///      <!ELEMENT prop-filter (is-not-defined |
///                             ((time-range | text-match)?,
///                               param-filter*))>
///
///      <!ATTLIST prop-filter name CDATA #REQUIRED>
///      name value: a calendar property name (e.g., ATTENDEE)
#[derive(Debug, PartialEq)]
pub struct PropFilter {
    pub name: Component,
    // None = Option 1, Some() = Option 2, 3 & 4
    pub additional_rules: Option<PropFilterRules>,
}
#[derive(Debug, PartialEq)]
pub enum PropFilterRules {
    // Option 2
    IsNotDefined,
    // Options 3 & 4
    Match(PropFilterMatch),
}
#[derive(Debug, PartialEq)]
pub struct PropFilterMatch {
    pub time_range: Option<TimeRange>,
    pub time_or_text: Option<TimeOrText>,
    pub param_filter: Vec<ParamFilter>,
}
#[derive(Debug, PartialEq)]
pub enum TimeOrText {
    Time(TimeRange),
    Text(TextMatch),
}

///  Name:  text-match
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  Specifies a substring match on a property or parameter
/// value.
///
/// Description:  The CALDAV:text-match XML element specifies text used
/// for a substring match against the property or parameter value
/// specified in a calendaring REPORT request.
///
/// The "collation" attribute is used to select the collation that the
/// server MUST use for character string matching.  In the absence of
/// this attribute, the server MUST use the "i;ascii-casemap"
/// collation.
///
/// The "negate-condition" attribute is used to indicate that this
/// test returns a match if the text matches when the attribute value
/// is set to "no", or return a match if the text does not match, if
/// the attribute value is set to "yes".  For example, this can be
/// used to match components with a STATUS property not set to
/// CANCELLED.
///
/// Definition:
/// <!ELEMENT text-match (#PCDATA)>
/// PCDATA value: string
///  <!ATTLIST text-match collation        CDATA "i;ascii-casemap"
///  negate-condition (yes | no) "no">
#[derive(Debug, PartialEq)]
pub struct TextMatch {
    pub collation: Option<Collation>,
    pub negate_condition: Option<bool>,
    pub text: String,
}

/// Name:  param-filter
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  Limits the search to specific parameter values.
///
/// Description:  The CALDAV:param-filter XML element specifies a query
/// targeted at a specific calendar property parameter (e.g.,
/// PARTSTAT) in the scope of the calendar property on which it is
/// defined.  A calendar property parameter is said to match a CALDAV:
/// param-filter if:
///
///   *  The CALDAV:param-filter XML element is empty and a parameter of
///      the type specified by the "name" attribute exists on the
///      calendar property being examined;
///
///   or:
///
///   *  The CALDAV:param-filter XML element contains a CALDAV:is-not-
///      defined XML element and no parameter of the type specified by
///      the "name" attribute exists on the calendar property being
///      examined;
///
/// Definition:
///
///      <!ELEMENT param-filter (is-not-defined | text-match?)>
///
///      <!ATTLIST param-filter name CDATA #REQUIRED>
///        name value: a property parameter name (e.g., PARTSTAT)
#[derive(Debug, PartialEq)]
pub struct ParamFilter {
    pub name: PropertyParameter,
    pub additional_rules: Option<ParamFilterMatch>,
}
#[derive(Debug, PartialEq)]
pub enum ParamFilterMatch {
    IsNotDefined,
    Match(TextMatch),
}

/// CALDAV:is-not-defined XML Element
///
/// Name:  is-not-defined
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  Specifies that a match should occur if the enclosing
/// component, property, or parameter does not exist.
///
/// Description:  The CALDAV:is-not-defined XML element specifies that a
/// match occurs if the enclosing component, property, or parameter
/// value specified in a calendaring REPORT request does not exist in
/// the calendar data being tested.
///
/// Definition:
/// <!ELEMENT is-not-defined EMPTY>
/* CURRENTLY INLINED */



/// Name:  timezone
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  Specifies the time zone component to use when determining
/// the results of a report.
///
/// Description:  The CALDAV:timezone XML element specifies that for a
/// given calendaring REPORT request, the server MUST rely on the
/// specified VTIMEZONE component instead of the CALDAV:calendar-
/// timezone property of the calendar collection, in which the
/// calendar object resource is contained to resolve "date" values and
/// "date with local time" values (i.e., floating time) to "date with
/// UTC time" values.  The server will require this information to
/// determine if a calendar component scheduled with "date" values or
/// "date with local time" values intersects a CALDAV:time-range
/// specified in a CALDAV:calendar-query REPORT.
///
/// Note:  The iCalendar data embedded within the CALDAV:timezone XML
/// element MUST follow the standard XML character data encoding
/// rules, including use of &lt;, &gt;, &amp; etc. entity encoding or
/// the use of a <![CDATA[ ... ]]> construct.  In the later case, the
///
/// iCalendar data cannot contain the character sequence "]]>", which
/// is the end delimiter for the CDATA section.
///
/// Definition:
///
/// <!ELEMENT timezone (#PCDATA)>
/// PCDATA value: an iCalendar object with exactly one VTIMEZONE
#[derive(Debug, PartialEq)]
pub struct TimeZone(pub String);

/// Name:  filter
///
/// Namespace:  urn:ietf:params:xml:ns:caldav
///
/// Purpose:  Specifies a filter to limit the set of calendar components
/// returned by the server.
///
/// Description:  The CALDAV:filter XML element specifies the search
/// filter used to limit the calendar components returned by a
/// calendaring REPORT request.
///
/// Definition:
/// <!ELEMENT filter (comp-filter)>
#[derive(Debug, PartialEq)]
pub struct Filter(pub CompFilter);

/// Name: time-range
///
/// Definition:
///
/// <!ELEMENT time-range EMPTY>
/// <!ATTLIST time-range start CDATA #IMPLIED
///                      end   CDATA #IMPLIED>
/// start value: an iCalendar "date with UTC time"
/// end value: an iCalendar "date with UTC time"
#[derive(Debug, PartialEq)]
pub enum TimeRange {
    OnlyStart(DateTime<Utc>),
    OnlyEnd(DateTime<Utc>),
    FullRange(DateTime<Utc>, DateTime<Utc>),
}

// ----------------------- ENUM ATTRIBUTES ---------------------

/// Known components
#[derive(Debug, PartialEq)]
pub enum Component {
    VCalendar,
    VJournal,
    VFreeBusy,
    VEvent,
    VTodo,
    VAlarm,
    VTimeZone,
    Unknown(String),
}
impl Component {
    pub fn as_str<'a>(&'a self) -> &'a str {
        match self {
            Self::VCalendar => "VCALENDAR",
            Self::VJournal => "VJOURNAL",
            Self::VFreeBusy => "VFREEBUSY",
            Self::VEvent => "VEVENT",
            Self::VTodo => "VTODO",
            Self::VAlarm => "VALARM",
            Self::VTimeZone => "VTIMEZONE",
            Self::Unknown(c) => c,
        }
    }
}

/// name="VERSION", name="SUMMARY", etc.
/// Can be set on different objects: VCalendar, VEvent, etc.
/// Might be replaced by an enum later
#[derive(Debug, PartialEq)]
pub struct ComponentProperty(pub String);

/// like PARSTAT
#[derive(Debug, PartialEq)]
pub struct PropertyParameter(pub String);
impl PropertyParameter {
    pub fn as_str<'a>(&'a self) -> &'a str {
        self.0.as_str()
    }
}

#[derive(Default,Debug,PartialEq)]
pub enum Collation {
    #[default]
    AsciiCaseMap,
    Octet,
    Unknown(String),
}
impl Collation {
    pub fn as_str<'a>(&'a self) -> &'a str {
        match self {
            Self::AsciiCaseMap => "i;ascii-casemap",
            Self::Octet => "i;octet",
            Self::Unknown(c) => c.as_str(),
        }
    }
}