1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5package lunatask
6
7import (
8 "encoding/json"
9 "errors"
10 "fmt"
11 "strings"
12)
13
14// Errors returned by Priority operations.
15var (
16 // ErrInvalidPriority is returned when parsing an unknown priority string.
17 ErrInvalidPriority = errors.New("invalid priority")
18 // ErrPriorityOutOfRange is returned when a priority value is outside [-2, 2].
19 ErrPriorityOutOfRange = errors.New("priority out of range")
20)
21
22// Priority represents task priority level from lowest (-2) to highest (2).
23// The default priority is [PriorityNormal] (0).
24type Priority int
25
26// Task priority levels. See [Priority] for the full range.
27const (
28 PriorityLowest Priority = -2
29 PriorityLow Priority = -1
30 PriorityNormal Priority = 0
31 PriorityHigh Priority = 1
32 PriorityHighest Priority = 2
33)
34
35// String returns the lowercase name of the priority level.
36func (p *Priority) String() string {
37 switch *p {
38 case PriorityLowest:
39 return "lowest"
40 case PriorityLow:
41 return "low"
42 case PriorityNormal:
43 return "normal"
44 case PriorityHigh:
45 return "high"
46 case PriorityHighest:
47 return "highest"
48 default:
49 return fmt.Sprintf("Priority(%d)", *p)
50 }
51}
52
53// Valid reports whether the priority is within the valid range [-2, 2].
54func (p *Priority) Valid() bool {
55 return *p >= PriorityLowest && *p <= PriorityHighest
56}
57
58// AllPriorities returns all valid priority values from lowest to highest.
59func AllPriorities() []Priority {
60 return []Priority{
61 PriorityLowest,
62 PriorityLow,
63 PriorityNormal,
64 PriorityHigh,
65 PriorityHighest,
66 }
67}
68
69// ParsePriority parses a string to a Priority value (case-insensitive).
70// Valid values: "lowest", "low", "normal", "high", "highest".
71func ParsePriority(str string) (Priority, error) {
72 switch strings.ToLower(str) {
73 case "lowest":
74 return PriorityLowest, nil
75 case "low":
76 return PriorityLow, nil
77 case "normal":
78 return PriorityNormal, nil
79 case "high":
80 return PriorityHigh, nil
81 case "highest":
82 return PriorityHighest, nil
83 default:
84 return 0, fmt.Errorf("%w: %q", ErrInvalidPriority, str)
85 }
86}
87
88// MarshalJSON implements [json.Marshaler].
89// Priority marshals as its integer value.
90func (p *Priority) MarshalJSON() ([]byte, error) {
91 data, err := json.Marshal(int(*p))
92 if err != nil {
93 return nil, fmt.Errorf("marshaling priority: %w", err)
94 }
95
96 return data, nil
97}
98
99// UnmarshalJSON implements [json.Unmarshaler].
100// Priority unmarshals from an integer value in the range [-2, 2].
101func (p *Priority) UnmarshalJSON(data []byte) error {
102 if string(data) == "null" {
103 *p = PriorityNormal
104
105 return nil
106 }
107
108 var val int
109 if err := json.Unmarshal(data, &val); err != nil {
110 return fmt.Errorf("priority must be an integer: %w", err)
111 }
112
113 if val < -2 || val > 2 {
114 return fmt.Errorf("%w: %d", ErrPriorityOutOfRange, val)
115 }
116
117 *p = Priority(val)
118
119 return nil
120}