package policies

import (
	"errors"

	"github.com/rackspace/gophercloud"
	"github.com/rackspace/gophercloud/pagination"
)

// Validation errors returned by create or update operations.
var (
	ErrNoName            = errors.New("Policy name cannot by empty.")
	ErrNoArgs            = errors.New("Args cannot be nil for schedule policies.")
	ErrInvalidAdjustment = errors.New("Invalid adjustment type.")
)

// List returns all scaling policies for a group.
func List(client *gophercloud.ServiceClient, groupID string) pagination.Pager {
	url := listURL(client, groupID)

	createPageFn := func(r pagination.PageResult) pagination.Page {
		return PolicyPage{pagination.SinglePageBase(r)}
	}

	return pagination.NewPager(client, url, createPageFn)
}

// CreateOptsBuilder is the interface responsible for generating the map that
// will be marshalled to JSON for a Create operation.
type CreateOptsBuilder interface {
	ToPolicyCreateMap() ([]map[string]interface{}, error)
}

// Adjustment represents the change in capacity associated with a policy.
type Adjustment struct {
	// The type for this adjustment.
	Type AdjustmentType

	// The value of the adjustment.  For adjustments of type Change or
	// DesiredCapacity, this will be converted to an integer.
	Value float64
}

// AdjustmentType represents the way in which a policy will change a group.
type AdjustmentType string

// Valid types of adjustments for a policy.
const (
	Change          AdjustmentType = "change"
	ChangePercent   AdjustmentType = "changePercent"
	DesiredCapacity AdjustmentType = "desiredCapacity"
)

// CreateOpts is a slice of CreateOpt structs that allow the user to create
// multiple policies in a single operation.
type CreateOpts []CreateOpt

// CreateOpt represents the options to create a policy.
type CreateOpt struct {
	// Name [required] is a name for the policy.
	Name string

	// Type [required] of policy, i.e. either "webhook" or "schedule".
	Type Type

	// Cooldown [required] period in seconds.
	Cooldown int

	// Adjustment [requried] type and value for the policy.
	Adjustment Adjustment

	// Additional configuration options for some types of policy.
	Args map[string]interface{}
}

// ToPolicyCreateMap converts a slice of CreateOpt structs into a map for use
// in the request body of a Create operation.
func (opts CreateOpts) ToPolicyCreateMap() ([]map[string]interface{}, error) {
	var policies []map[string]interface{}

	for _, o := range opts {
		if o.Name == "" {
			return nil, ErrNoName
		}

		if o.Type == Schedule && o.Args == nil {
			return nil, ErrNoArgs
		}

		policy := make(map[string]interface{})

		policy["name"] = o.Name
		policy["type"] = o.Type
		policy["cooldown"] = o.Cooldown

		if err := setAdjustment(o.Adjustment, policy); err != nil {
			return nil, err
		}

		if o.Args != nil {
			policy["args"] = o.Args
		}

		policies = append(policies, policy)
	}

	return policies, nil
}

// Create requests a new policy be created and associated with the given group.
func Create(client *gophercloud.ServiceClient, groupID string, opts CreateOptsBuilder) CreateResult {
	var res CreateResult

	reqBody, err := opts.ToPolicyCreateMap()

	if err != nil {
		res.Err = err
		return res
	}

	_, res.Err = client.Post(createURL(client, groupID), reqBody, &res.Body, nil)

	return res
}

// Get requests the details of a single policy with the given ID.
func Get(client *gophercloud.ServiceClient, groupID, policyID string) GetResult {
	var result GetResult

	_, result.Err = client.Get(getURL(client, groupID, policyID), &result.Body, nil)

	return result
}

// UpdateOptsBuilder is the interface responsible for generating the map
// structure for producing JSON for an Update operation.
type UpdateOptsBuilder interface {
	ToPolicyUpdateMap() (map[string]interface{}, error)
}

// UpdateOpts represents the options for updating an existing policy.
//
// Update operations completely replace the configuration being updated. Empty
// values in the update are accepted and overwrite previously specified
// parameters.
type UpdateOpts struct {
	// Name [required] is a name for the policy.
	Name string

	// Type [required] of policy, i.e. either "webhook" or "schedule".
	Type Type

	// Cooldown [required] period in seconds.  If you don't specify a cooldown,
	// it will default to zero, and the policy will be configured as such.
	Cooldown int

	// Adjustment [requried] type and value for the policy.
	Adjustment Adjustment

	// Additional configuration options for some types of policy.
	Args map[string]interface{}
}

// ToPolicyUpdateMap converts an UpdateOpts struct into a map for use as the
// request body in an Update request.
func (opts UpdateOpts) ToPolicyUpdateMap() (map[string]interface{}, error) {
	if opts.Name == "" {
		return nil, ErrNoName
	}

	if opts.Type == Schedule && opts.Args == nil {
		return nil, ErrNoArgs
	}

	policy := make(map[string]interface{})

	policy["name"] = opts.Name
	policy["type"] = opts.Type
	policy["cooldown"] = opts.Cooldown

	if err := setAdjustment(opts.Adjustment, policy); err != nil {
		return nil, err
	}

	if opts.Args != nil {
		policy["args"] = opts.Args
	}

	return policy, nil
}

// Update requests the configuration of the given policy be updated.
func Update(client *gophercloud.ServiceClient, groupID, policyID string, opts UpdateOptsBuilder) UpdateResult {
	var result UpdateResult

	url := updateURL(client, groupID, policyID)
	reqBody, err := opts.ToPolicyUpdateMap()

	if err != nil {
		result.Err = err
		return result
	}

	_, result.Err = client.Put(url, reqBody, nil, &gophercloud.RequestOpts{
		OkCodes: []int{204},
	})

	return result
}

// Delete requests the given policy be permanently deleted.
func Delete(client *gophercloud.ServiceClient, groupID, policyID string) DeleteResult {
	var result DeleteResult

	url := deleteURL(client, groupID, policyID)
	_, result.Err = client.Delete(url, &gophercloud.RequestOpts{
		OkCodes: []int{204},
	})

	return result
}

// Execute requests the given policy be executed immediately.
func Execute(client *gophercloud.ServiceClient, groupID, policyID string) ExecuteResult {
	var result ExecuteResult

	url := executeURL(client, groupID, policyID)
	_, result.Err = client.Post(url, nil, &result.Body, &gophercloud.RequestOpts{
		OkCodes: []int{202},
	})

	return result
}

// Validate and set an adjustment on the given request body.
func setAdjustment(adjustment Adjustment, reqBody map[string]interface{}) error {
	key := string(adjustment.Type)

	switch adjustment.Type {
	case ChangePercent:
		reqBody[key] = adjustment.Value

	case Change, DesiredCapacity:
		reqBody[key] = int(adjustment.Value)

	default:
		return ErrInvalidAdjustment
	}

	return nil
}
