package perm

import (
	"sort"
	"strings"

	"code.justin.tv/beefcake/server/rpc/beefcake"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
)

// AttachedPermissions is a list of sortable, marshallable permissions
type AttachedPermissions []*beefcake.AttachedPermission

// Len implements sort.Interface
func (ap AttachedPermissions) Len() int { return len(ap) }

// Less implements sort.Interface
func (ap AttachedPermissions) Less(i, j int) bool { return strings.Compare(ap[i].Id, ap[j].Id) < 0 }

// Swap implements sort.Interface
func (ap AttachedPermissions) Swap(i, j int) { ap[i], ap[j] = ap[j], ap[i] }

// MarshalDynamoDBAttributeValue implements dynamodbattribute.Marshaller
func (ap AttachedPermissions) MarshalDynamoDBAttributeValue(av *dynamodb.AttributeValue) error {
	if len(ap) == 0 {
		av.SetM(map[string]*dynamodb.AttributeValue{})
		return nil
	}

	out := make(map[string]Permission, len(ap))
	for _, perm := range ap {
		out[perm.GetId()] = Permission(*perm.GetPermission())
	}

	res, err := dynamodbattribute.Marshal(out)
	if err != nil {
		return err
	}

	*av = *res
	return nil
}

// UnmarshalDynamoDBAttributeValue implements dynamodbattribute.Unmarshaller
func (ap *AttachedPermissions) UnmarshalDynamoDBAttributeValue(av *dynamodb.AttributeValue) error {
	var out map[string]Permission

	if err := dynamodbattribute.Unmarshal(av, &out); err != nil {
		return err
	}

	aps := make([]*beefcake.AttachedPermission, 0, len(out))
	for permID, perm := range out {
		perm := beefcake.Permission(perm)
		aps = append(aps, &beefcake.AttachedPermission{
			Id:         permID,
			Permission: &perm,
		})
	}

	*ap = AttachedPermissions(aps)
	sort.Sort(ap)

	return nil
}
