// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package application

import (
	"log"

	"mojo/public/go/bindings"
	"mojo/public/go/system"

	sp "mojo/public/interfaces/application/service_provider"
	"mojo/public/interfaces/bindings/service_describer"
)

type connectionInfo struct {
	requestorURL  string
	connectionURL string
}

// RequestorURL returns the URL of application that established the connection.
func (c *connectionInfo) RequestorURL() string {
	return c.requestorURL
}

// ConnectionURL returns the URL that was used by the source application to
// establish a connection to the destination application.
func (c *connectionInfo) ConnectionURL() string {
	return c.connectionURL
}

// ServiceRequest is an interface request for a specified mojo service.
type ServiceRequest interface {
	// Name returns the name of requested mojo service.
	Name() string

	// ServiceDescription returns a service description, which can be queried to
	// examine the type information of the service associated with this
	// ServiceRequest.
	// Note: In some implementations, the ServiceDescription returned will not
	// provide type information. Methods called may return nil or an error.
	ServiceDescription() service_describer.ServiceDescription

	// PassMessagePipe passes ownership of the underlying message pipe
	// handle to the newly created handle object, invalidating the
	// underlying handle object in the process.
	PassMessagePipe() system.MessagePipeHandle
}

// ServiceFactory provides implementation of a mojo service.
type ServiceFactory interface {
	// Name returns the name of provided mojo service.
	Name() string

	// ServiceDescription returns a service description, which can be queried to
	// examine the type information of the mojo service associated with this
	// ServiceFactory.
	// Note: In some implementations, the ServiceDescription returned will not
	// provide type information. Methods called may return nil or an error.
	ServiceDescription() service_describer.ServiceDescription

	// Create binds an implementation of mojo service to the provided
	// message pipe and runs it.
	Create(pipe system.MessagePipeHandle)
}

// Connection represents a connection to another application. An instance of
// this struct is passed to Delegate's AcceptConnection() function each time a
// connection is made to this application.
// TODO(vtl): This is largely overkill now that we no longer have "wrong way"
// service providers (a.k.a. "exposed services"). Things should be simplified.
// https://github.com/domokit/mojo/issues/762
type Connection struct {
	connectionInfo
	// Request for local services. Is valid until ProvideServices is called.
	servicesRequest *sp.ServiceProvider_Request
	// Indicates that ProvideServices function was already called.
	servicesProvided   bool
	localServices      *bindings.Stub
	outgoingConnection *OutgoingConnection
	isClosed           bool
	// Is set if ProvideServicesWithDescriber was called.
	// Note: When DescribeServices is invoked, some implementations may return
	// incomplete ServiceDescriptions. For example, if type information was not
	// generated, then the methods called may return nil or an error.
	describer *ServiceDescriberFactory
}

func newConnection(requestorURL string, services sp.ServiceProvider_Request, resolvedURL string) *Connection {
	info := connectionInfo{
		requestorURL,
		resolvedURL,
	}
	return &Connection{
		connectionInfo:  info,
		servicesRequest: &services,
		outgoingConnection: &OutgoingConnection{
			info,
			nil,
		},
	}
}

// ProvideServices starts a service provider on a separate goroutine that
// provides given services to the remote application. Returns a pointer to
// outgoing connection that can be used to connect to services provided by
// remote application.
// Panics if called more than once.
func (c *Connection) ProvideServices(services ...ServiceFactory) *OutgoingConnection {
	if c.servicesProvided {
		panic("ProvideServices or ProvideServicesWithDescriber can be called only once")
	}
	c.servicesProvided = true
	if c.servicesRequest == nil {
		return c.outgoingConnection
	}
	if len(services) == 0 {
		c.servicesRequest.PassMessagePipe().Close()
		return c.outgoingConnection
	}

	provider := &serviceProviderImpl{
		make(map[string]ServiceFactory),
	}
	for _, service := range services {
		provider.AddService(service)
	}
	c.localServices = sp.NewServiceProviderStub(*c.servicesRequest, provider, bindings.GetAsyncWaiter())
	go func() {
		for {
			if err := c.localServices.ServeRequest(); err != nil {
				connectionError, ok := err.(*bindings.ConnectionError)
				if !ok || !connectionError.Closed() {
					log.Println(err)
				}
				break
			}
		}
	}()
	return c.outgoingConnection
}

// ProvideServicesWithDescriber is an alternative to ProvideServices that, in
// addition to providing the given services, also provides type descriptions of
// the given services. See ProvideServices for a description of what it does.
// This method will invoke ProvideServices after appending the ServiceDescriber
// service to |services|. See service_describer.mojom for a description of the
// ServiceDescriber interface. Client Mojo applications can choose to connect
// to this ServiceDescriber interface, which describes the other services listed
// in |services|.
// Note that the implementation of ServiceDescriber will make the optional
// DeclarationData available on all types, and in particular, the names used in
// .mojom files will be exposed to client applications.
func (c *Connection) ProvideServicesWithDescriber(services ...ServiceFactory) *OutgoingConnection {
	if c.servicesProvided {
		panic("ProvideServices or ProvideServicesWithDescriber can be called only once")
	}
	mapping := make(map[string]service_describer.ServiceDescription)
	for _, service := range services {
		mapping[service.Name()] = service.ServiceDescription()
	}
	c.describer = newServiceDescriberFactory(mapping)
	servicesWithDescriber := append(services, &service_describer.ServiceDescriber_ServiceFactory{c.describer})

	return c.ProvideServices(servicesWithDescriber...)
}

// Close closes both incoming and outgoing parts of the connection.
func (c *Connection) Close() {
	if c.servicesRequest != nil {
		c.servicesRequest.Close()
	}
	if c.localServices != nil {
		c.localServices.Close()
	}
	if c.describer != nil {
		c.describer.Close()
	}
	if c.outgoingConnection.remoteServices != nil {
		c.outgoingConnection.remoteServices.Close_Proxy()
	}
	c.isClosed = true
}

// OutgoingConnection represents outgoing part of connection to another
// application. In order to close it close the |Connection| object that returned
// this |OutgoingConnection|.
type OutgoingConnection struct {
	connectionInfo
	remoteServices *sp.ServiceProvider_Proxy
}

// ConnectToService asks remote application to provide a service through the
// message pipe endpoint supplied by the caller.
func (c *OutgoingConnection) ConnectToService(request ServiceRequest) {
	pipe := request.PassMessagePipe()
	if c.remoteServices == nil {
		pipe.Close()
		return
	}
	c.remoteServices.ConnectToService(request.Name(), pipe)
}

// serviceProviderImpl is an implementation of mojo ServiceProvider interface.
type serviceProviderImpl struct {
	factories map[string]ServiceFactory
}

// Mojo ServiceProvider implementation.
func (sp *serviceProviderImpl) ConnectToService(name string, messagePipe system.MessagePipeHandle) error {
	factory, ok := sp.factories[name]
	if !ok {
		messagePipe.Close()
		return nil
	}
	factory.Create(messagePipe)
	return nil
}

func (sp *serviceProviderImpl) AddService(factory ServiceFactory) {
	sp.factories[factory.Name()] = factory
}
