package internal

import (
	"github.com/trivago/tgo/tcontainer"
	"gitlab.com/pcanilho/go-jira"
	"io"
)

type IssueAttachment struct {
	io.Reader
	Filename string
}

type Controller interface {
	IssueController
	UserController
	ProjectController
}

type IssueCreationOptions struct {
	Assignee, Summary, Description, Project, IssueType string
	CustomFields                                       tcontainer.MarshalMap
	Labels, Components                                 []string
	Comment, Priority                                  string
	Attachments                                        []*IssueAttachment
}

type IssueController interface {
	// CreateIssue creates a Jira issue using the provided @param IssueCreationOptions object instance.
	// 	@return the instance pointer of the newly created Jira issue.
	//  @return an error if the Jira issue was not successfully created.
	CreateIssue(*IssueCreationOptions) (*jira.Issue, error)
	// CloneIssue creates a Jira issue using an existing issue as a base template. As a parameter, both the instance
	//	pointer and a ticket identifier (key or ID) can be provided.
	//	@return the instance pointer of the newly created Jira issue.
	//  @return an error if the Jira issue was not successfully created.
	CloneIssue(interface{}) (*jira.Issue, error)
	// SearchIssues searches for Jira issues with a provided JQL query in string format.
	//	@param the JQL query.
	// 	@param the *jira.SearchOptions (based of the upstream `go-jira` library)
	//  @param if greater than 0, an error will be returned whenever the search result is greater than the specified value.
	//		Useful when using piped commands. i.e. xargs, etc.
	//	@return a slice of Jira issues that match the provided JQL query.
	//  @return an error if the provided JQL query is not valid.
	SearchIssues(string, *jira.SearchOptions, int) ([]jira.Issue, error)
	// GetIssue returns the pointer to a Jira issue instance that corresponds to the provided identifier (key or ID) in
	//		string format.
	//	@param the Jira issue identifier representing either the issue key or internal ID.
	//	@param the *jira.GetQueryOptions (based of the upstream `go-jira` library).
	//	@return the instance pointer of the Jira issue matching the provided identifier.
	//	@return an error if no Jira issue was found to be matching the provided identifier.
	GetIssue(string, *jira.GetQueryOptions) (*jira.Issue, error)
	// UpdateIssue returns the pointer of the newly updated Jira issue.
	//	@param the instance pointer to a Jira issue or an identifier in string format representing either the issue key
	//		or internal ID.
	//	@param the fields & properties of the provided Jira issue identifier that will be updated.
	//	@return the pointer of the newly updated Jira issue.
	// 	@return an error if the provided identifier does not match an existing issue or if the issue was not
	//		successfully updated.
	UpdateIssue(interface{}, map[string]interface{}) (*jira.Issue, error)
	// AddCommentToIssue returns a instance pointer to a newly created Jira issue comment (@see *jira.Comment).
	//	An error is returned instead if the comment was not successfully added to the Jira issue.
	//	@param the instance pointer to a Jira issue or an identifier in string format representing either the issue key
	//		or internal ID.
	//	@param the comment body in string format to be added to the Jira issue.
	//	@return the instance pointer to the upstream *jira.Comment object for further manipulation.
	// 	@return an error if the provided identifier does not match an existing issue or if the issue was not
	//		successfully updated with the new comment.
	AddCommentToIssue(interface{}, string) (*jira.Comment, error)
	// UploadAttachmentsToIssue uploads/attaches files to the provided Jira issue. An error is returned instead if this
	//	process does not succeed.
	//	@param the instance pointer to a Jira issue or an identifier in string format representing either the issue key
	//		or internal ID.
	// 	@param a variadic *IssueAttachment struct that represents a file path to be uploaded/attached to a Jira issue.
	//	@return an error if any of the provided files fail to be uploaded/attached to the Jira issue.
	UploadAttachmentsToIssue(interface{}, ...*IssueAttachment) error
	// DeleteIssue deletes a Jira issue that matches the provided identifier.
	//	@param the instance pointer to a Jira issue or an identifier in string format representing either the issue key
	//		or internal ID.
	//	@return an error if the Jira issue was not deleted successfully.
	DeleteIssue(interface{}) error
}

type BoardController interface {
	GetBoard(string) (*jira.Board, error)
	GetBoardIssues(string) ([]jira.Issue, error)
}

type UserController interface {
	GetUser(string) (*jira.User, error)
}

type ProjectController interface {
	SearchProjects(...string) ([]jira.Project, error)
}