package main

import (
	"log"
	"sync"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/discovery"
	"v.io/v23/security/access"
	"v.io/v23/verror"
	idiscovery "v.io/x/ref/lib/discovery"
	"v.io/x/ref/lib/discovery/plugins/ble"
	"v.io/x/ref/lib/discovery/plugins/mdns"

	_ "v.io/x/ref/runtime/factories/generic"

	mojom "mojom/vanadium/discovery"

	"mojo/public/go/application"
	"mojo/public/go/bindings"
	"mojo/public/go/system"
)

//#include "mojo/public/c/system/types.h"
import "C"

type discoveryService struct {
	mu           sync.Mutex
	ctx          *context.T
	s            discovery.T
	trigger      *idiscovery.Trigger
	nextAdv      int32
	pendingAdvs  map[int32]chan struct{}
	nextScan     int32
	pendingScans map[int32]chan struct{}
}

func convertToErrorStruct(err error) *mojom.Error {
	outErr := &mojom.Error{
		Id:  "v.io/verror/Unknown",
		Msg: err.Error(),
	}
	if e, ok := err.(verror.E); ok {
		outErr.Id = string(e.ID)
		outErr.Action = int32(e.Action)
	}
	return outErr
}

func (d *discoveryService) Advertise(s mojom.Service, patterns []string) (int32, *mojom.Error, error) {
	vService := discovery.Service{
		InstanceUuid:  s.InstanceUuid,
		InterfaceName: s.InterfaceName,
		Attrs:         discovery.Attributes(s.Attrs),
		Addrs:         s.Addrs,
	}

	ctx, c := context.WithCancel(d.ctx)

	err := d.s.Advertise(ctx, vService, access.Permissions{})
	if err != nil {
		return 0, convertToErrorStruct(err), nil
	}
	ch := make(chan struct{})
	d.mu.Lock()
	id := d.nextAdv
	d.pendingAdvs[id] = ch
	d.nextAdv++
	d.mu.Unlock()
	d.trigger.Add(c, ch)
	return id, nil, nil
}

func (d *discoveryService) StopAdvertising(handle int32) error {
	d.mu.Lock()
	ch := d.pendingAdvs[handle]
	d.mu.Unlock()
	if ch != nil {
		close(ch)
	}
	return nil
}

func vServiceTomService(s discovery.Service) mojom.Service {
	return mojom.Service{
		InstanceUuid:  s.InstanceUuid,
		InterfaceName: s.InterfaceName,
		Attrs:         s.Attrs,
		Addrs:         s.Addrs,
	}
}

func (d *discoveryService) Scan(query string, scanHandler mojom.ScanHandler_Pointer) (int32, *mojom.Error, error) {
	ctx, c := context.WithCancel(d.ctx)
	proxy := mojom.NewScanHandlerProxy(scanHandler, bindings.GetAsyncWaiter())
	scanCh, err := d.s.Scan(ctx, query)
	if err != nil {
		return 0, convertToErrorStruct(err), nil
	}
	ch := make(chan struct{})
	d.mu.Lock()
	id := d.nextScan
	d.pendingScans[id] = ch
	d.nextScan++
	d.mu.Unlock()

	d.trigger.Add(c, ch)
	go func() {
		for v := range scanCh {
			switch value := v.Interface().(type) {
			case discovery.UpdateFound:
				proxy.Found(vServiceTomService(value.Value.Service))
			case discovery.UpdateLost:
				proxy.Lost(vServiceTomService(value.Value.Service))
			}
		}
	}()
	return id, nil, nil
}

func (d *discoveryService) StopScan(handle int32) error {
	d.mu.Lock()
	ch := d.pendingScans[handle]
	d.mu.Unlock()
	if ch != nil {
		close(ch)
	}
	return nil
}

func (d *discoveryService) stop() {
	d.mu.Lock()
	for _, ch := range d.pendingScans {
		close(ch)
	}

	for _, ch := range d.pendingAdvs {
		close(ch)
	}
	d.mu.Unlock()
}

type discoveryDelegate struct {
	stubs    []*bindings.Stub
	impl     *discoveryService
	shutdown v23.Shutdown
}

func (d *discoveryDelegate) Initialize(c application.Context) {
	ctx, shutdown := v23.Init()
	host := c.Args()[0]
	log.Println("Starting discovery with name", host)
	mplugin, err := mdns.New(host)
	if err != nil {
		log.Println("Failed to start mplugin", err)
	}

	bplugin, err := ble.NewPlugin(host)
	if err != nil {
		log.Println("Failed to start bplugin", err)
	}

	d.impl = &discoveryService{
		ctx:          ctx,
		trigger:      idiscovery.NewTrigger(),
		s:            idiscovery.New([]idiscovery.Plugin{mplugin, bplugin}),
		pendingAdvs:  map[int32]chan struct{}{},
		pendingScans: map[int32]chan struct{}{},
	}
	d.shutdown = shutdown
}

func (d *discoveryDelegate) Create(request mojom.Discoverer_Request) {
	stub := mojom.NewDiscovererStub(request, d.impl, bindings.GetAsyncWaiter())
	d.stubs = append(d.stubs, stub)
	go func() {
		for {
			if err := stub.ServeRequest(); err != nil {
				connectionErr, ok := err.(*bindings.ConnectionError)
				if !ok || !connectionErr.Closed() {
					log.Println(err)
				}
				break
			}
		}
	}()
}

func (d *discoveryDelegate) AcceptConnection(connection *application.Connection) {
	connection.ProvideServices(&mojom.Discoverer_ServiceFactory{d})
}

func (d *discoveryDelegate) Quit() {
	d.impl.stop()
	d.shutdown()
	for _, stub := range d.stubs {
		stub.Close()
	}
}

//export MojoMain
func MojoMain(handle C.MojoHandle) C.MojoResult {
	application.Run(&discoveryDelegate{}, system.MojoHandle(handle))
	return C.MOJO_RESULT_OK
}

func main() {
}
