package hybrid

import (
	"fmt"
	"strings"

	"cwtch.im/cwtch/model"
	"cwtch.im/cwtch/model/constants"
	"cwtch.im/cwtch/peer"
)

func (f *ManagedGroupFunctionality) checkHybridGroup(profile peer.CwtchPeer, cid int) (*model.Conversation, error) {
	if profile.IsFeatureEnabled(constants.GroupsExperiment) {
		if ci, err := profile.GetConversationInfo(cid); err == nil {
			if ci.IsHybridGroup() {
				return ci, nil
			}
			return nil, fmt.Errorf("not a hybrid group")
		} else {
			return nil, err
		}
	}
	return nil, fmt.Errorf("hybrid group feature is not enabled")
}

func (f *ManagedGroupFunctionality) ChangeRole(profile peer.CwtchPeer, cid int, handle string, targetRole model.Role) error {
	if ci, err := f.checkHybridGroup(profile, cid); err == nil {
		myAcl := ci.GetMemberRole(profile.GetOnion()).ComputeEffectiveACL(ci.GroupMode())
		if myAcl.Promote {
			currentRole := ci.GetMemberRole(handle).ComputeEffectiveACL(ci.GroupMode()).AssignedRole
			if myAcl.AssignedRole.IsAbleToPromoteTo(currentRole, targetRole, ci.GroupMode()) {
				_, err := SendMessageToManagedGroup(profile, cid, ci.Handle, ChangeMemberRoleEvent{
					Handle:  handle,
					NewRole: targetRole,
				})
				return err
			}
		}
		return fmt.Errorf("role does not have permission to change role")
	} else {
		return err
	}
}

func (f *ManagedGroupFunctionality) InviteMember(profile peer.CwtchPeer, cid int, handle string) error {
	if ci, err := f.checkHybridGroup(profile, cid); err == nil {
		if ci.GetMemberRole(profile.GetOnion()).ComputeEffectiveACL(ci.GroupMode()).Invite {

			_, err := SendMessageToManagedGroup(profile, cid, ci.Handle, AddMemberEvent{
				Handle: handle,
			})
			return err
		}
		return fmt.Errorf("role does not have permission to invite member")
	} else {
		return err
	}
}

func (f *ManagedGroupFunctionality) KickMember(profile peer.CwtchPeer, cid int, handle string) error {
	if ci, err := f.checkHybridGroup(profile, cid); err == nil {
		if ci.GetMemberRole(profile.GetOnion()).ComputeEffectiveACL(ci.GroupMode()).Kick {

			_, err := SendMessageToManagedGroup(profile, cid, ci.Handle, RemoveMemberEvent{
				Handle: handle,
			})
			return err
		}
		return fmt.Errorf("role does not have permission to invite member")
	} else {
		return err
	}
}

func (f *ManagedGroupFunctionality) ChangeGroupMode(profile peer.CwtchPeer, cid int, partialGroupMode string) error {
	if ci, err := f.checkHybridGroup(profile, cid); err == nil {
		if ci.GetMemberRole(profile.GetOnion()).ComputeEffectiveACL(ci.GroupMode()).ChangeAllChannelModes {
			mode := model.GroupMode(0)
			mptr := &mode
			mptr.UnmarshalText([]byte(partialGroupMode))
			_, err := SendMessageToManagedGroup(profile, cid, ci.Handle, ChangeGroupModeEvent{
				GroupMode: mode,
				Additive:  strings.HasPrefix(partialGroupMode, "+"),
			})
			return err
		}
		return fmt.Errorf("role does not have permission to invite member")
	} else {
		return err
	}
}
