1package pagerduty
2
3import (
4	"fmt"
5	"net/http"
6
7	"github.com/google/go-querystring/query"
8)
9
10const (
11	escPath = "/escalation_policies"
12)
13
14// EscalationRule is a rule for an escalation policy to trigger.
15type EscalationRule struct {
16	ID      string      `json:"id,omitempty"`
17	Delay   uint        `json:"escalation_delay_in_minutes,omitempty"`
18	Targets []APIObject `json:"targets"`
19}
20
21// EscalationPolicy is a collection of escalation rules.
22type EscalationPolicy struct {
23	APIObject
24	Name            string           `json:"name,omitempty"`
25	EscalationRules []EscalationRule `json:"escalation_rules,omitempty"`
26	Services        []APIReference   `json:"services,omitempty"`
27	NumLoops        uint             `json:"num_loops,omitempty"`
28	Teams           []APIReference   `json:"teams,omitempty"`
29	Description     string           `json:"description,omitempty"`
30	RepeatEnabled   bool             `json:"repeat_enabled,omitempty"`
31}
32
33// ListEscalationPoliciesResponse is the data structure returned from calling the ListEscalationPolicies API endpoint.
34type ListEscalationPoliciesResponse struct {
35	APIListObject
36	EscalationPolicies []EscalationPolicy `json:"escalation_policies"`
37}
38
39type ListEscalationRulesResponse struct {
40	APIListObject
41	EscalationRules []EscalationRule `json:"escalation_rules"`
42}
43
44// ListEscalationPoliciesOptions is the data structure used when calling the ListEscalationPolicies API endpoint.
45type ListEscalationPoliciesOptions struct {
46	APIListObject
47	Query    string   `url:"query,omitempty"`
48	UserIDs  []string `url:"user_ids,omitempty,brackets"`
49	TeamIDs  []string `url:"team_ids,omitempty,brackets"`
50	Includes []string `url:"include,omitempty,brackets"`
51	SortBy   string   `url:"sort_by,omitempty"`
52}
53
54// GetEscalationRuleOptions is the data structure used when calling the GetEscalationRule API endpoint.
55type GetEscalationRuleOptions struct {
56	Includes []string `url:"include,omitempty,brackets"`
57}
58
59// ListEscalationPolicies lists all of the existing escalation policies.
60func (c *Client) ListEscalationPolicies(o ListEscalationPoliciesOptions) (*ListEscalationPoliciesResponse, error) {
61	v, err := query.Values(o)
62	if err != nil {
63		return nil, err
64	}
65	resp, err := c.get(escPath + "?" + v.Encode())
66	if err != nil {
67		return nil, err
68	}
69	var result ListEscalationPoliciesResponse
70	return &result, c.decodeJSON(resp, &result)
71}
72
73// CreateEscalationPolicy creates a new escalation policy.
74func (c *Client) CreateEscalationPolicy(e EscalationPolicy) (*EscalationPolicy, error) {
75	data := make(map[string]EscalationPolicy)
76	data["escalation_policy"] = e
77	resp, err := c.post(escPath, data, nil)
78	return getEscalationPolicyFromResponse(c, resp, err)
79}
80
81// DeleteEscalationPolicy deletes an existing escalation policy and rules.
82func (c *Client) DeleteEscalationPolicy(id string) error {
83	_, err := c.delete(escPath + "/" + id)
84	return err
85}
86
87// GetEscalationPolicyOptions is the data structure used when calling the GetEscalationPolicy API endpoint.
88type GetEscalationPolicyOptions struct {
89	Includes []string `url:"include,omitempty,brackets"`
90}
91
92// GetEscalationPolicy gets information about an existing escalation policy and its rules.
93func (c *Client) GetEscalationPolicy(id string, o *GetEscalationPolicyOptions) (*EscalationPolicy, error) {
94	v, err := query.Values(o)
95	if err != nil {
96		return nil, err
97	}
98	resp, err := c.get(escPath + "/" + id + "?" + v.Encode())
99	return getEscalationPolicyFromResponse(c, resp, err)
100}
101
102// UpdateEscalationPolicy updates an existing escalation policy and its rules.
103func (c *Client) UpdateEscalationPolicy(id string, e *EscalationPolicy) (*EscalationPolicy, error) {
104	data := make(map[string]EscalationPolicy)
105	data["escalation_policy"] = *e
106	resp, err := c.put(escPath+"/"+id, data, nil)
107	return getEscalationPolicyFromResponse(c, resp, err)
108}
109
110// CreateEscalationRule creates a new escalation rule for an escalation policy
111// and appends it to the end of the existing escalation rules.
112func (c *Client) CreateEscalationRule(escID string, e EscalationRule) (*EscalationRule, error) {
113	data := make(map[string]EscalationRule)
114	data["escalation_rule"] = e
115	resp, err := c.post(escPath+"/"+escID+"/escalation_rules", data, nil)
116	return getEscalationRuleFromResponse(c, resp, err)
117}
118
119// GetEscalationRule gets information about an existing escalation rule.
120func (c *Client) GetEscalationRule(escID string, id string, o *GetEscalationRuleOptions) (*EscalationRule, error) {
121	v, err := query.Values(o)
122	if err != nil {
123		return nil, err
124	}
125	resp, err := c.get(escPath + "/" + escID + "/escalation_rules/" + id + "?" + v.Encode())
126	return getEscalationRuleFromResponse(c, resp, err)
127}
128
129// DeleteEscalationRule deletes an existing escalation rule.
130func (c *Client) DeleteEscalationRule(escID string, id string) error {
131	_, err := c.delete(escPath + "/" + escID + "/escalation_rules/" + id)
132	return err
133}
134
135// UpdateEscalationRule updates an existing escalation rule.
136func (c *Client) UpdateEscalationRule(escID string, id string, e *EscalationRule) (*EscalationRule, error) {
137	data := make(map[string]EscalationRule)
138	data["escalation_rule"] = *e
139	resp, err := c.put(escPath+"/"+escID+"/escalation_rules/"+id, data, nil)
140	return getEscalationRuleFromResponse(c, resp, err)
141}
142
143// ListEscalationRules lists all of the escalation rules for an existing escalation policy.
144func (c *Client) ListEscalationRules(escID string) (*ListEscalationRulesResponse, error) {
145	resp, err := c.get(escPath + "/" + escID + "/escalation_rules")
146	if err != nil {
147		return nil, err
148	}
149
150	var result ListEscalationRulesResponse
151	return &result, c.decodeJSON(resp, &result)
152}
153
154func getEscalationRuleFromResponse(c *Client, resp *http.Response, err error) (*EscalationRule, error) {
155	defer resp.Body.Close()
156	if err != nil {
157		return nil, err
158	}
159	var target map[string]EscalationRule
160	if dErr := c.decodeJSON(resp, &target); dErr != nil {
161		return nil, fmt.Errorf("Could not decode JSON response: %v", dErr)
162	}
163	rootNode := "escalation_rule"
164	t, nodeOK := target[rootNode]
165	if !nodeOK {
166		return nil, fmt.Errorf("JSON response does not have %s field", rootNode)
167	}
168	return &t, nil
169}
170
171func getEscalationPolicyFromResponse(c *Client, resp *http.Response, err error) (*EscalationPolicy, error) {
172	defer resp.Body.Close()
173	if err != nil {
174		return nil, err
175	}
176	var target map[string]EscalationPolicy
177	if dErr := c.decodeJSON(resp, &target); dErr != nil {
178		return nil, fmt.Errorf("Could not decode JSON response: %v", dErr)
179	}
180	rootNode := "escalation_policy"
181	t, nodeOK := target[rootNode]
182	if !nodeOK {
183		return nil, fmt.Errorf("JSON response does not have %s field", rootNode)
184	}
185	return &t, nil
186}
187