package manager

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/dynamodb"
)

// ListNamespaces lists all namespaces
func (m *Manager) ListNamespaces() ([]string, error) {
	scanInput := m.inputForNamespaceScan()
	namespaces := make([]string, 0, 0)

	for {
		scanOutput, err := m.dynamoDB().Scan(scanInput)
		if err != nil {
			return nil, err
		}
		for _, item := range scanOutput.Items {
			namespaces = append(namespaces, *item["namespace"].S)
		}

		if scanOutput.LastEvaluatedKey == nil {
			break
		} else {
			scanInput.ExclusiveStartKey = scanOutput.LastEvaluatedKey
		}
	}
	return namespaces, nil
}

func (m *Manager) inputForNamespaceScan() *dynamodb.ScanInput {
	return &dynamodb.ScanInput{
		ReturnConsumedCapacity: aws.String("INDEXES"),
		TableName:              aws.String(m.NamespaceTableName()),
	}
}

// ListNamespace lists all secrets in a namespace
func (m *Manager) ListNamespace(namespace string) ([]*Secret, error) {
	queryInput := m.inputForListNamespaceQuery(namespace)
	return m.querySecrets(queryInput)

}

func (m *Manager) inputForListNamespaceQuery(namespace string) *dynamodb.QueryInput {
	return &dynamodb.QueryInput{
		ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
			":namespace": {
				S: aws.String(namespace),
			},
		},
		IndexName:              aws.String("namespace_name"),
		KeyConditionExpression: aws.String("namespace = :namespace"),
		ReturnConsumedCapacity: aws.String("INDEXES"),
		TableName:              aws.String(m.Config.stack().SecretsTableName()),
	}
}

// querySecrets will query dynamodb until all Secrets have been returned
func (m *Manager) querySecrets(queryInput *dynamodb.QueryInput) ([]*Secret, error) {
	var secrets []*Secret

	for {
		queryOutput, err := m.dynamoDB().Query(queryInput)
		if err != nil {
			return nil, err
		}
		for _, item := range queryOutput.Items {
			secret, err := unmarshalSecret(item)
			if err != nil {
				return nil, err
			}
			secrets = append(secrets, secret)
		}

		if queryOutput.LastEvaluatedKey == nil {
			break
		} else {
			queryInput.ExclusiveStartKey = queryOutput.LastEvaluatedKey
		}
	}
	return secrets, nil

}
