1package gerrit
2
3import (
4	"fmt"
5)
6
7// ReviewerInfo entity contains information about a reviewer and its votes on a change.
8type ReviewerInfo struct {
9	AccountInfo
10	Approvals map[string]string `json:"approvals"`
11}
12
13// SuggestedReviewerInfo entity contains information about a reviewer that can be added to a change (an account or a group).
14type SuggestedReviewerInfo struct {
15	Account AccountInfo   `json:"account,omitempty"`
16	Group   GroupBaseInfo `json:"group,omitempty"`
17}
18
19// AddReviewerResult entity describes the result of adding a reviewer to a change.
20type AddReviewerResult struct {
21	Input     string         `json:"input,omitempty"`
22	Reviewers []ReviewerInfo `json:"reviewers,omitempty"`
23	CCS       []ReviewerInfo `json:"ccs,omitempty"`
24	Error     string         `json:"error,omitempty"`
25	Confirm   bool           `json:"confirm,omitempty"`
26}
27
28// DeleteVoteInput entity contains options for the deletion of a vote.
29//
30// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#delete-vote-input
31type DeleteVoteInput struct {
32	Label         string                `json:"label,omitempty"`
33	Notify        string                `json:"notify,omitempty"`
34	NotifyDetails map[string]NotifyInfo `json:"notify_details"`
35}
36
37// ListReviewers lists the reviewers of a change.
38//
39// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#list-reviewers
40func (s *ChangesService) ListReviewers(changeID string) (*[]ReviewerInfo, *Response, error) {
41	u := fmt.Sprintf("changes/%s/reviewers/", changeID)
42
43	req, err := s.client.NewRequest("GET", u, nil)
44	if err != nil {
45		return nil, nil, err
46	}
47
48	v := new([]ReviewerInfo)
49	resp, err := s.client.Do(req, v)
50	if err != nil {
51		return nil, resp, err
52	}
53
54	return v, resp, err
55}
56
57// SuggestReviewers suggest the reviewers for a given query q and result limit n.
58// If result limit is not passed, then the default 10 is used.
59//
60// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#suggest-reviewers
61func (s *ChangesService) SuggestReviewers(changeID string, opt *QueryOptions) (*[]SuggestedReviewerInfo, *Response, error) {
62	u := fmt.Sprintf("changes/%s/suggest_reviewers", changeID)
63
64	u, err := addOptions(u, opt)
65	if err != nil {
66		return nil, nil, err
67	}
68
69	req, err := s.client.NewRequest("GET", u, nil)
70	if err != nil {
71		return nil, nil, err
72	}
73
74	v := new([]SuggestedReviewerInfo)
75	resp, err := s.client.Do(req, v)
76	if err != nil {
77		return nil, resp, err
78	}
79
80	return v, resp, err
81}
82
83// GetReviewer retrieves a reviewer of a change.
84//
85// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-reviewer
86func (s *ChangesService) GetReviewer(changeID, accountID string) (*ReviewerInfo, *Response, error) {
87	u := fmt.Sprintf("changes/%s/reviewers/%s", changeID, accountID)
88
89	req, err := s.client.NewRequest("GET", u, nil)
90	if err != nil {
91		return nil, nil, err
92	}
93
94	v := new(ReviewerInfo)
95	resp, err := s.client.Do(req, v)
96	if err != nil {
97		return nil, resp, err
98	}
99
100	return v, resp, err
101}
102
103// AddReviewer adds one user or all members of one group as reviewer to the change.
104// The reviewer to be added to the change must be provided in the request body as a ReviewerInput entity.
105//
106// As response an AddReviewerResult entity is returned that describes the newly added reviewers.
107// If a group is specified, adding the group members as reviewers is an atomic operation.
108// This means if an error is returned, none of the members are added as reviewer.
109// If a group with many members is added as reviewer a confirmation may be required.
110//
111// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#add-reviewer
112func (s *ChangesService) AddReviewer(changeID string, input *ReviewerInput) (*AddReviewerResult, *Response, error) {
113	u := fmt.Sprintf("changes/%s/reviewers", changeID)
114
115	req, err := s.client.NewRequest("POST", u, input)
116	if err != nil {
117		return nil, nil, err
118	}
119
120	v := new(AddReviewerResult)
121	resp, err := s.client.Do(req, v)
122	if err != nil {
123		return nil, resp, err
124	}
125
126	return v, resp, err
127}
128
129// DeleteReviewer deletes a reviewer from a change.
130//
131// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#delete-reviewer
132func (s *ChangesService) DeleteReviewer(changeID, accountID string) (*Response, error) {
133	u := fmt.Sprintf("changes/%s/reviewers/%s", changeID, accountID)
134	return s.client.DeleteRequest(u, nil)
135}
136
137// ListVotes lists the votes for a specific reviewer of the change.
138//
139// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#list-votes
140func (s *ChangesService) ListVotes(changeID string, accountID string) (map[string]int, *Response, error) {
141	u := fmt.Sprintf("changes/%s/reviewers/%s/votes/", changeID, accountID)
142	req, err := s.client.NewRequest("GET", u, nil)
143	if err != nil {
144		return nil, nil, err
145	}
146
147	var v map[string]int
148	resp, err := s.client.Do(req, &v)
149	if err != nil {
150		return nil, resp, err
151	}
152	return v, resp, err
153}
154
155// DeleteVote deletes a single vote from a change. Note, that even when the
156// last vote of a reviewer is removed the reviewer itself is still listed on
157// the change.
158//
159// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#delete-vote
160func (s *ChangesService) DeleteVote(changeID string, accountID string, label string, input *DeleteVoteInput) (*Response, error) {
161	u := fmt.Sprintf("changes/%s/reviewers/%s/votes/%s", changeID, accountID, label)
162	return s.client.DeleteRequest(u, input)
163}
164