package storage

import (
	"gorm.io/gorm"
)

//go:generate go build -o RolesGenerator ../cmd/RolesGenerator/main.go
//go:generate ./RolesGenerator -input=roles.go -output=rolesUtil_generated.go
//go:generate rm RolesGenerator

// A role is, in concept, similar to how Discord handles roles
// Some permission can be either disallowed (&false), don't care (nil) or allowed (&true)
// Don't care just says to use the value from the next lower role where it is set
type Role struct {
	// TODO: More control options
	// Extend upon whatever Masto, Akkoma and Misskey have
	// Lots of details please

	// --- Role metadata ---

	// Include full db model stuff
	gorm.Model

	// Name of the role
	Name string

	// Priority of the role
	// Lower priority gets applied first and thus overwritten by higher priority ones
	// If two roles have the same priority, the order is undetermined and may be random
	// Default priority for new roles is 1 to always overwrite default user
	// And full admin has max priority possible
	Priority uint
	// Whether this role is for a for a single user only (like custom, per user permissions in Discord)
	// If yes, Name will be the id of the user in question
	IsUserRole bool

	// Whether this role is one built into Linstrom from the start or not
	// Note: Built-in roles can't be modified
	IsBuiltIn bool

	// --- User permissions ---
	CanSendMedia             *bool
	CanSendCustomEmotes      *bool
	CanSendCustomReactions   *bool
	CanSendPublicNotes       *bool
	CanSendLocalNotes        *bool
	CanSendFollowerOnlyNotes *bool
	CanSendPrivateNotes      *bool
	CanSendReplies           *bool
	CanQuote                 *bool
	CanBoost                 *bool
	CanIncludeLinks          *bool
	CanIncludeSurvey         *bool

	CanChangeDisplayName *bool

	BlockedUsers     []string `gorm:"type:bytes;serializer:gob"`
	CanSubmitReports *bool
	CanLogin         *bool

	CanMentionOthers     *bool
	HasMentionCountLimit *bool
	MentionLimit         *uint32

	// CanViewBoosts *bool
	// CanViewQuotes *bool
	// CanViewMedia *bool
	// CanViewCustomEmotes *bool

	// --- Automod ---
	AutoNsfwMedia                *bool
	AutoCwPosts                  *bool
	AutoCwPostsText              *string
	ScanCreatedPublicNotes       *bool
	ScanCreatedLocalNotes        *bool
	ScanCreatedFollowerOnlyNotes *bool
	ScanCreatedPrivateNotes      *bool
	DisallowInteractionsWith     []string `gorm:"type:bytes;serializer:gob"`

	WithholdNotesForManualApproval *bool
	WithholdNotesBasedOnRegex      *bool
	WithholdNotesRegexes           []string `gorm:"type:bytes;serializer:gob"`

	// --- Admin perms ---
	// If set, counts as all permissions being set as given and all restrictions being disabled
	FullAdmin                          *bool
	CanAffectOtherAdmins               *bool
	CanDeleteNotes                     *bool
	CanConfirmWithheldNotes            *bool
	CanAssignRoles                     *bool
	CanSupressInteractionsBetweenUsers *bool
	CanOverwriteDisplayNames           *bool
	CanManageCustomEmotes              *bool
	CanViewDeletedNotes                *bool
	CanRecoverDeletedNotes             *bool
	CanManageAvatarDecorations         *bool
	CanManageAds                       *bool
	CanSendAnnouncements               *bool
}

/*
Mastodon permissions (highest permission to lowest):
- Admin
- Devops
- View Audit log
- View Dashboard
- Manage Reports
- Manage Federation
- Manage Settings
- Manage Blocks
- Manage Taxonomies
- Manage Appeals
- Manage Users
- Manage Invites
- Manage Rules
- Manage Announcements
- Manage Custom Emojis
- Manage Webhooks
- Invite Users
- Manage Roles
- Manage User Access
- Delete User Data
*/

/*
Misskey "permissions" (no order):
- Global timeline available (interact with global timeline I think)
- Local timeline available (same as global, but for local)
- b-something timeline available
- Can send public notes
- How many mentions a note can have
- Can invite others
- How many invites can be sent
- InviteLimitCycle (whatever that means)
- Invite Expiration time (duration of how long invites stay valid I think)
- Manage custom emojis
- Manage custom avatar decorations
- Seach for notes
- Use translator
- Hide ads from self
- How much storage space the user has
- Whether to mark all posts from account as nsfw
- max number of pinned messages
- max number of antennas
- max number of muted words
- max number of webhooks
- max number of clips
- max number of notes contained in a clip (? I think. Don't know enough about clips)
- Max number of lists of users
- max number of users in a user list
- rate limit multiplier
- max number of applied avatar decorations
*/

func (s *Storage) NewEmptyRole(name string) (*Role, error) {
	_, err := s.FindRoleByName(name)
	switch err {
	case nil:
		return nil, ErrEntryAlreadyExists
	case ErrEntryNotFound: // Empty case, since this is what we want
	default:
		return nil, err
	}

	newRole := Role{Name: name}
	err = s.db.Create(&newRole).Error
	if err != nil {
		return nil, err
	}
	return &newRole, nil
}

func (s *Storage) FindRoleByName(name string) (*Role, error) {
	role := Role{}
	err := s.db.Where("name = ?", name).First(&role).Error
	switch err {
	case nil:
		return &role, nil
	case gorm.ErrRecordNotFound:
		return nil, ErrEntryNotFound
	default:
		return nil, err
	}
}
