package inter

import (
	"errors"
	"strings"

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

// This functionality is a little different. It's not functionality per-se. It's a wrapper around
// CwtchProfile function that combines some core-functionalities like Hybrid Groups so that
// they can be transparently exposed in autobindings.
// DEV NOTE: consider moving other cross-cutting interface functions here to simplfy CwtchPeer
type InterfaceFunctionality struct {
}

// FunctionalityGate returns filesharing functionality - gates now happen on function calls.
func FunctionalityGate() *InterfaceFunctionality {
	return new(InterfaceFunctionality)
}

func (i InterfaceFunctionality) ImportBundle(profile peer.CwtchPeer, uri string) error {
	// check if this is a managed group. Note: managed groups do not comply with the server bundle format.
	if strings.HasPrefix(uri, "managed:") {
		uri = uri[len("managed:"):]
		if profile.IsFeatureEnabled(constants.GroupsExperiment) {
			mgf := hybrid.ManagedGroupFunctionality{}
			return mgf.NewManagedGroup(profile, uri)
		} else {
			return errors.New("managed groups require the group experiment to be enabled")
		}
	}
	// DEV NOTE: we may want to eventually move Server Import code to ServerFunctionality and add a hook here...
	// DEV NOTE: consider making ImportBundle a high-level functionality interface? to support different kinds of contacts?
	return profile.ImportBundle(uri)
}

// EnhancedImportBundle is identical to EnhancedImportBundle in CwtchPeer but instead of wrapping CwtchPeer.ImportBundle it instead
// wraps InterfaceFunctionality.ImportBundle
func (i InterfaceFunctionality) EnhancedImportBundle(profile peer.CwtchPeer, uri string) string {
	err := i.ImportBundle(profile, uri)
	if err == nil {
		return "importBundle.success"
	}
	return err.Error()
}

// SendMessage sends a message to a conversation.
// NOTE: Unlike CwtchPeer.SendMessage this interface makes no guarentees about the raw-ness of the message sent to peer contacts.
// If the conversation is a hybrid groups then the message may be wrapped in multiple layers of overlay messages / encryption
// prior to being send. To send a raw message to a peer then use peer.CwtchPeer
// DEV NOTE: Move Legacy Group message send here...
func (i InterfaceFunctionality) SendMessage(profile peer.CwtchPeer, conversation int, message string) (int, error) {
	ci, err := profile.GetConversationInfo(conversation)
	if err != nil {
		return -1, err
	}
	if ci.ACL[ci.Handle].ManageGroup {
		mgf := hybrid.ManagedGroupFunctionality{}
		return mgf.SendMessageToManagedGroup(profile, conversation, message)
	}
	return profile.SendMessage(conversation, message)
}

// EnhancedSendMessage Attempts to Send a Message and Immediately Attempts to Lookup the Message in the Database
// this wraps InterfaceFunctionality.SendMessage to support HybridGroups
func (i InterfaceFunctionality) EnhancedSendMessage(profile peer.CwtchPeer, conversation int, message string) string {
	mid, err := i.SendMessage(profile, conversation, message)
	if err != nil {
		return ""
	}
	return profile.EnhancedGetMessageById(conversation, mid)
}
