//
// Copyright 2021, Sander van Harmelen
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package gitlab

import (
	"net/http"
	"time"
)

type (
	ResourceGroupServiceInterface interface {
		GetAllResourceGroupsForAProject(pid any, options ...RequestOptionFunc) ([]*ResourceGroup, *Response, error)
		GetASpecificResourceGroup(pid any, key string, options ...RequestOptionFunc) (*ResourceGroup, *Response, error)
		ListUpcomingJobsForASpecificResourceGroup(pid any, key string, options ...RequestOptionFunc) ([]*Job, *Response, error)
		EditAnExistingResourceGroup(pid any, key string, opts *EditAnExistingResourceGroupOptions, options ...RequestOptionFunc) (*ResourceGroup, *Response, error)
	}

	// ResourceGroupService handles communication with the resource
	// group related methods of the GitLab API.
	//
	// GitLab API docs:
	// https://docs.gitlab.com/api/resource_groups/
	ResourceGroupService struct {
		client *Client
	}
)

var _ ResourceGroupServiceInterface = (*ResourceGroupService)(nil)

// ResourceGroup represents a GitLab Project Resource Group.
//
// GitLab API docs:
// https://docs.gitlab.com/api/resource_groups/
type ResourceGroup struct {
	ID          int64      `json:"id"`
	Key         string     `json:"key"`
	ProcessMode string     `json:"process_mode"`
	CreatedAt   *time.Time `json:"created_at"`
	UpdatedAt   *time.Time `json:"updated_at"`
}

// String gets a string representation of a ResourceGroup
//
// GitLab API docs:
// https://docs.gitlab.com/api/resource_groups/
func (rg ResourceGroup) String() string {
	return Stringify(rg)
}

// GetAllResourceGroupsForAProject allows you to get all resource
// groups associated with a given project.
//
// GitLab API docs:
// https://docs.gitlab.com/api/resource_groups/#get-all-resource-groups-for-a-project
func (s *ResourceGroupService) GetAllResourceGroupsForAProject(pid any, options ...RequestOptionFunc) ([]*ResourceGroup, *Response, error) {
	return do[[]*ResourceGroup](s.client,
		withPath("projects/%s/resource_groups", ProjectID{pid}),
		withRequestOpts(options...),
	)
}

// GetASpecificResourceGroup allows you to get a specific
// resource group for a given project.
//
// GitLab API docs:
// https://docs.gitlab.com/api/resource_groups/#get-a-specific-resource-group
func (s *ResourceGroupService) GetASpecificResourceGroup(pid any, key string, options ...RequestOptionFunc) (*ResourceGroup, *Response, error) {
	return do[*ResourceGroup](s.client,
		withPath("projects/%s/resource_groups/%s", ProjectID{pid}, key),
		withRequestOpts(options...),
	)
}

// ListUpcomingJobsForASpecificResourceGroup allows you to get all
// upcoming jobs for a specific resource group for a given project.
//
// GitLab API docs:
// https://docs.gitlab.com/api/resource_groups/#list-upcoming-jobs-for-a-specific-resource-group
func (s *ResourceGroupService) ListUpcomingJobsForASpecificResourceGroup(pid any, key string, options ...RequestOptionFunc) ([]*Job, *Response, error) {
	return do[[]*Job](s.client,
		withPath("projects/%s/resource_groups/%s/upcoming_jobs", ProjectID{pid}, key),
		withRequestOpts(options...),
	)
}

// EditAnExistingResourceGroupOptions represents the available
// EditAnExistingResourceGroup options.
//
// GitLab API docs:
// https://docs.gitlab.com/api/resource_groups/#edit-an-existing-resource-group
type EditAnExistingResourceGroupOptions struct {
	ProcessMode *ResourceGroupProcessMode `url:"process_mode,omitempty" json:"process_mode,omitempty"`
}

// EditAnExistingResourceGroup allows you to edit a specific
// resource group for a given project
//
// GitLab API docs:
// https://docs.gitlab.com/api/resource_groups/#edit-an-existing-resource-group
func (s *ResourceGroupService) EditAnExistingResourceGroup(pid any, key string, opts *EditAnExistingResourceGroupOptions, options ...RequestOptionFunc) (*ResourceGroup, *Response, error) {
	return do[*ResourceGroup](s.client,
		withMethod(http.MethodPut),
		withPath("projects/%s/resource_groups/%s", ProjectID{pid}, key),
		withAPIOpts(opts),
		withRequestOpts(options...),
	)
}
