package policy

import (
	"context"
	"errors"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/iam"
)

// List lists ALL roles (names only), even roles a user doesn't have access to modify
func (pg *IAMPolicyGenerator) List() (roles []string, err error) {
	roles = []string{}

	getMoreRoles := true
	var marker *string
	for getMoreRoles {
		input := &iam.ListRolesInput{
			PathPrefix: aws.String(pg.PathPrefix(IAMRolePathSuffix)),
			Marker:     marker,
			MaxItems:   aws.Int64(1000),
		}
		var listRolesOutput *iam.ListRolesOutput
		listRolesOutput, err = pg.IAM.ListRoles(input)
		if err != nil {
			return
		}
		getMoreRoles = aws.BoolValue(listRolesOutput.IsTruncated)
		marker = listRolesOutput.Marker

		for _, v := range listRolesOutput.Roles {
			roles = append(roles, aws.StringValue(v.RoleName))
		}
	}
	return
}

// ListPageInput contains parameters for listing a page of iam roles
type ListPageInput struct {
	First int64
	After string
}

func (input *ListPageInput) validate() error {
	if input.First < 1 {
		return errors.New("listpage: first must be > 0")
	}
	return nil
}

// ListPageOutput contains a page of iam roles
type ListPageOutput struct {
	Roles       []string
	HasNextPage bool
	Cursor      string
}

// ListPage returns a page of iam roles
func (pg *IAMPolicyGenerator) ListPage(ctx context.Context, input *ListPageInput) (output *ListPageOutput, err error) {
	if err = input.validate(); err != nil {
		return
	}

	params := &iam.ListRolesInput{
		PathPrefix: aws.String(pg.PathPrefix(IAMRolePathSuffix)),
		MaxItems:   aws.Int64(input.First),
	}
	if input.After != "" {
		params.Marker = aws.String(input.After)
	}

	resp, err := pg.IAM.ListRolesWithContext(ctx, params)
	if err != nil {
		return
	}

	output = &ListPageOutput{
		Roles:       make([]string, len(resp.Roles)),
		Cursor:      aws.StringValue(resp.Marker),
		HasNextPage: aws.BoolValue(resp.IsTruncated),
	}

	for i, v := range resp.Roles {
		output.Roles[i] = aws.StringValue(v.RoleName)
	}
	return
}
