package main

import (
	"log"
	"sync"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/discovery"
	"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, nil)
	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.(type) {
			case discovery.UpdateFound:
				proxy.Found(vServiceTomService(value.Value.Service))
			case discovery.UpdateLost:
				proxy.Lost(vServiceTomService(value.Value.Service))
			default:
			}
		}
	}()
	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()[1]
	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() {
}
