package entity

import "fmt"

var (
	CreatingClusterStatus         []ClusterStatus       = []ClusterStatus{ClusterStatusInitializing, ClusterStatusPreparing, ClusterStatusLaunching}
	DeletedClusterStatus          []ClusterStatus       = []ClusterStatus{ClusterStatusDeleted, ClusterStatusDeletecomplete}
	DeletedOrClearedClusterStatus []ClusterStatus       = []ClusterStatus{ClusterStatusDeleted, ClusterStatusDeletecomplete, ClusterStatusCleared}
	ReadyForBackupClusterStatus   []ClusterStatus       = []ClusterStatus{ClusterStatusNormal}
	ValidUserRoles                map[UserRole]struct{} = map[UserRole]struct{}{UserRoleOwner: {}, UserRoleMember: {}, UserRoleBillingAdmin: {}, UserRoleAuditAdmin: {}}
	ValidUserProjectRoles         map[UserRole]struct{} = map[UserRole]struct{}{UserRoleProjectOwner: {}, UserRoleProjectDev: {}, UserRoleProjectReadOnly: {}}

	ValidUserOrgRbacRoles map[string]struct{} = map[string]struct{}{
		RoleOrgOwner:         {},
		RoleOrgMember:        {},
		RoleOrgAuditAdmin:    {},
		RoleOrgBillingAdmin:  {},
		RoleOrgBillingViewer: {},
	}
	ValidUserProjectRbacRoles map[string]struct{} = map[string]struct{}{
		RoleProjectOwner:          {},
		RoleProjectDev:            {},
		RoleProjectReadOnly:       {},
		RoleProjectCtlPlaneViewer: {},
	}

	ValidClusterRbacRoles = map[string]struct{}{
		RoleClusterAdmin:  {},
		RoleClusterViewer: {},
	}

	ValidUserPartnerRbacRoles = map[string]struct{}{
		RolePartnerAdmin: {},
		RoleOrgOwner:     {},
	}
)

// Creating returns true if we are still creating the cluster
func (s ClusterStatus) Creating() bool {
	for _, tmp := range CreatingClusterStatus {
		if s == tmp {
			return true
		}
	}
	return false
}

// Deleted returns true if cluster is deleted
func (s ClusterStatus) Deleted() bool {
	for _, tmp := range DeletedClusterStatus {
		if s == tmp {
			return true
		}
	}
	return false
}

// DeletedOrCleared returns true if cluster is deleted or cleared
func (s ClusterStatus) DeletedOrCleared() bool {
	for _, tmp := range DeletedOrClearedClusterStatus {
		if s == tmp {
			return true
		}
	}
	return false
}

// ReadyForBackup returns true is cluster is ready for backup
func (c Cluster) ReadyForBackup() bool {
	for _, tmp := range ReadyForBackupClusterStatus {
		if c.Status == tmp {
			return true
		}
	}
	if c.Status == ClusterStatusDeleted && c.FinalBackupBeforeDelete {
		return true
	}
	return false
}

// IsDevTier returns true if cluster is dev tier
func (c Cluster) IsDevTier() bool {
	// TODO(chenfei): It is NOT the best strategy to detect whether the cluster is dev tier.
	return c.Free
}

func GetEntityIDsFromProjects(projects []Project) []ID {
	entityIDs := make([]ID, len(projects))
	for i, project := range projects {
		entityIDs[i] = project.ID
	}
	return entityIDs
}

func GetEntityIDsFromTenants(tenants []Tenant) []ID {
	entityIDs := make([]ID, len(tenants))
	for i, tenant := range tenants {
		entityIDs[i] = tenant.ID
	}
	return entityIDs
}

func GetEntityIDsFromUsers(users []User) []ID {
	entityIDs := make([]ID, len(users))
	for i, user := range users {
		entityIDs[i] = user.ID
	}
	return entityIDs
}

func FormatUserName(firstName, lastName string) string {
	return fmt.Sprintf("%s %s", firstName, lastName)
}

func MakeIDList(list []uint64) []ID {
	result := make([]ID, len(list))
	for i, id := range list {
		result[i] = ID(id)
	}

	return result
}

func GetTargetIDFromRoleBindings(bindings []RoleBinding) []uint64 {
	targetIDs := make([]uint64, len(bindings))
	for i, binding := range bindings {
		targetIDs[i] = binding.TargetID.Uint64()
	}
	return targetIDs
}

func GetScopeIDFromRoleBindings(bindings []RoleBinding) []uint64 {
	scopeIDs := make([]uint64, len(bindings))
	for i, binding := range bindings {
		scopeIDs[i] = binding.ScopeID.Uint64()
	}
	return scopeIDs
}

var RoleBindingRole2DbRoleMap = map[string]string{
	RoleOrgOwner:        DbRoleAdmin,
	RoleProjectOwner:    DbRoleAdmin,
	RoleProjectDev:      DbRoleReadWrite,
	RoleProjectReadOnly: DbRoleReadOnly,
}
