package main

import (
	"encoding/hex"
	"log"
	"sync"

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

	"mojom/v.io/x/ref/services/discovery/ble/ble"
	"v.io/x/ref/services/discovery/ble/internal/lib"
)

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

type bleImpl struct {
	n *lib.BleNeighborHood
	d *delegate
}

func (b *bleImpl) Advertise(adv ble.Advertisement) (ble.PluginStopper_Pointer, error) {
	uuid := hex.EncodeToString(adv.ServiceId)
	b.n.AddService(uuid, adv.Service)
	return b.createHandleFor(&stopAdvertingImpl{uuid: uuid, n: b.n}), nil
}

func (b *bleImpl) Scan(uuid *[]uint8, attr map[string]string, handler ble.PluginScanHandler_Pointer) (ble.PluginStopper_Pointer, error) {
	ch := make(chan *update, 10)
	proxy := ble.NewPluginScanHandlerProxy(handler, bindings.GetAsyncWaiter())
	go func() {
		for v := range ch {
			if v.found {
				proxy.Found(v.adv)
			} else {
				proxy.Lost(v.adv)
			}
		}
	}()
	id := b.n.AddScanner(uuid, attr, ch)
	return b.createHandleFor(&stopScanImpl{id: id, n: b.n}), nil
}

func (b *bleImpl) createHandleFor(h ble.PluginStopper) ble.PluginStopper_Pointer {
	req, ptr := ble.CreateMessagePipeForPluginStopper()
	stub := ble.NewPluginStopperStub(req, h, bindings.GetAsyncWaiter())
	b.d.addStub(stub)
	go func() {
		for {
			if err := stub.ServeRequest(); err != nil {
				connErr, ok := err.(*bindings.ConnectionError)
				if !ok || !connErr.Closed() {
					log.Println(err)
				}
				break
			}
		}
	}()

	return ptr
}

type stopAdvertingImpl struct {
	uuid string
	n    *bleNeighborHood
}

func (s *stopAdvertingImpl) Stop() error {
	s.n.removeService(s.uuid)
	return nil
}

type stopScanImpl struct {
	id int64
	n  *bleNeighborHood
}

func (s *stopScanImpl) Stop() error {
	s.n.removeScanner(s.id)
	return nil
}

type delegate struct {
	mu    sync.Mutex
	n     *bleNeighborHood
	stubs []*bindings.Stub
}

func (d *delegate) Initialize(ctx application.Context) {
	args := ctx.Args()
	if len(args) < 2 {
		log.Println("Device name needs to be passed in")
		ctx.Close()
	}
	name := ctx.Args()[1]
	n, err := newBleNeighborhood(name)
	if err != nil {
		log.Println("Failed to start neighborhood", err)
		ctx.Close()
	}
	d.n = n
}

func (d *delegate) Create(req ble.V23Ble_Request) {
	stub := ble.NewV23BleStub(req, &bleImpl{n: d.n, d: d}, bindings.GetAsyncWaiter())
	d.addStub(stub)
	go func() {
		for {
			if err := stub.ServeRequest(); err != nil {
				connErr, ok := err.(*bindings.ConnectionError)
				if !ok || !connErr.Closed() {
					log.Println(err)
				}
				break
			}
		}
	}()
}

func (d *delegate) addStub(s *bindings.Stub) {
	d.mu.Lock()
	d.stubs = append(d.stubs, s)
	d.mu.Unlock()
}
func (d *delegate) AcceptConnection(conn *application.Connection) {
	conn.ProvideServices(&ble.V23Ble_ServiceFactory{d})
}

func (d *delegate) Quit() {
	for _, stub := range d.stubs {
		stub.Close()
	}
	if d.n != nil {
		d.n.Stop()
	}
}

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

func main() {}
