package varlink

import (
	"strings"
)

// RegistryInterface holds metadata about a Varlink interface.
type RegistryInterface struct {
	Name       string
	Definition string
}

// Registry acts as a request dispatcher that routes Varlink calls to
// appropriate interface handlers based on the method namespace.
type Registry struct {
	// interfaces holds a mapping between a Varlink namespace and
	// RegistryInterface. It is populated by the library users, by
	// calling the Register method.
	interfaces map[string]RegistryInterface
	handlers   map[string]Handler
}

func NewRegistry() *Registry {
	return &Registry{
		interfaces: make(map[string]RegistryInterface),
		handlers:   make(map[string]Handler),
	}
}

// Add registers a new namespace and handler with the registry. This
// gets called from autogenerated code inside the Register method.
func (r *Registry) Add(iface *RegistryInterface, handler Handler) {
	r.interfaces[iface.Name] = *iface
	r.handlers[iface.Name] = handler
}

// HandleVarlink dispatches calls to the appropriate interface handlers.
func (r *Registry) HandleVarlink(call *ServerCall, req *ServerRequest) error {
	lastDot := strings.LastIndexByte(req.Method, '.')
	if lastDot <= 0 {
		lastDot = 0
	}

	handler, ok := r.handlers[req.Method[:lastDot]]
	if !ok {
		return &ServerError{
			Name:       "org.varlink.service.InterfaceNotFound",
			Parameters: map[string]string{"interface": req.Method},
		}
	}

	return handler.HandleVarlink(call, req)
}
