package gatt

import (
	"log"

	"github.com/paypal/gatt/xpc"
)

type peripheral struct {
	// NameChanged is called whenever the peripheral GAP Device name has changed.
	NameChanged func(Peripheral)

	// ServicesModified is called when one or more service of a peripheral have changed.
	// A list of invalid service is provided in the parameter.
	ServicesModified func(Peripheral, []*Service)

	d    *device
	svcs []*Service

	sub *subscriber

	id   xpc.UUID
	name string

	reqc  chan message
	rspc  chan message
	quitc chan struct{}
}

func NewPeripheral(u UUID) Peripheral { return &peripheral{id: xpc.UUID(u.b)} }

func (p *peripheral) Device() Device       { return p.d }
func (p *peripheral) ID() string           { return p.id.String() }
func (p *peripheral) Name() string         { return p.name }
func (p *peripheral) Services() []*Service { return p.svcs }

func (p *peripheral) DiscoverServices(ss []UUID) ([]*Service, error) {
	rsp := p.sendReq(44, xpc.Dict{
		"kCBMsgArgDeviceUUID": p.id,
		"kCBMsgArgUUIDs":      uuidSlice(ss),
	})
	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
		return nil, attEcode(res)
	}
	svcs := []*Service{}
	for _, xss := range rsp["kCBMsgArgServices"].(xpc.Array) {
		xs := xss.(xpc.Dict)
		u := MustParseUUID(xs.MustGetHexBytes("kCBMsgArgUUID"))
		h := uint16(xs.MustGetInt("kCBMsgArgServiceStartHandle"))
		endh := uint16(xs.MustGetInt("kCBMsgArgServiceEndHandle"))
		svcs = append(svcs, &Service{uuid: u, h: h, endh: endh})
	}
	p.svcs = svcs
	return svcs, nil
}

func (p *peripheral) DiscoverIncludedServices(ss []UUID, s *Service) ([]*Service, error) {
	rsp := p.sendReq(60, xpc.Dict{
		"kCBMsgArgDeviceUUID":         p.id,
		"kCBMsgArgServiceStartHandle": s.h,
		"kCBMsgArgServiceEndHandle":   s.endh,
		"kCBMsgArgUUIDs":              uuidSlice(ss),
	})
	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
		return nil, attEcode(res)
	}
	// TODO
	return nil, notImplemented
}

func (p *peripheral) DiscoverCharacteristics(cs []UUID, s *Service) ([]*Characteristic, error) {
	rsp := p.sendReq(61, xpc.Dict{
		"kCBMsgArgDeviceUUID":         p.id,
		"kCBMsgArgServiceStartHandle": s.h,
		"kCBMsgArgServiceEndHandle":   s.endh,
		"kCBMsgArgUUIDs":              uuidSlice(cs),
	})
	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
		return nil, attEcode(res)
	}
	for _, xcs := range rsp.MustGetArray("kCBMsgArgCharacteristics") {
		xc := xcs.(xpc.Dict)
		u := MustParseUUID(xc.MustGetHexBytes("kCBMsgArgUUID"))
		ch := uint16(xc.MustGetInt("kCBMsgArgCharacteristicHandle"))
		vh := uint16(xc.MustGetInt("kCBMsgArgCharacteristicValueHandle"))
		props := Property(xc.MustGetInt("kCBMsgArgCharacteristicProperties"))
		c := &Characteristic{uuid: u, svc: s, props: props, h: ch, vh: vh}
		s.chars = append(s.chars, c)
	}
	return s.chars, nil
}

func (p *peripheral) DiscoverDescriptors(ds []UUID, c *Characteristic) ([]*Descriptor, error) {
	rsp := p.sendReq(69, xpc.Dict{
		"kCBMsgArgDeviceUUID":                p.id,
		"kCBMsgArgCharacteristicHandle":      c.h,
		"kCBMsgArgCharacteristicValueHandle": c.vh,
		"kCBMsgArgUUIDs":                     uuidSlice(ds),
	})
	for _, xds := range rsp.MustGetArray("kCBMsgArgDescriptors") {
		xd := xds.(xpc.Dict)
		u := MustParseUUID(xd.MustGetHexBytes("kCBMsgArgUUID"))
		h := uint16(xd.MustGetInt("kCBMsgArgDescriptorHandle"))
		d := &Descriptor{uuid: u, char: c, h: h}
		c.descs = append(c.descs, d)
	}
	return c.descs, nil
}

func (p *peripheral) ReadCharacteristic(c *Characteristic) ([]byte, error) {
	rsp := p.sendReq(64, xpc.Dict{
		"kCBMsgArgDeviceUUID":                p.id,
		"kCBMsgArgCharacteristicHandle":      c.h,
		"kCBMsgArgCharacteristicValueHandle": c.vh,
	})
	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
		return nil, attEcode(res)
	}
	b := rsp.MustGetBytes("kCBMsgArgData")
	return b, nil
}

func (p *peripheral) WriteCharacteristic(c *Characteristic, b []byte, noRsp bool) error {
	args := xpc.Dict{
		"kCBMsgArgDeviceUUID":                p.id,
		"kCBMsgArgCharacteristicHandle":      c.h,
		"kCBMsgArgCharacteristicValueHandle": c.vh,
		"kCBMsgArgData":                      b,
		"kCBMsgArgType":                      map[bool]int{false: 0, true: 1}[noRsp],
	}
	if noRsp {
		p.sendCmd(65, args)
		return nil
	}
	rsp := p.sendReq(65, args)
	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
		return attEcode(res)
	}
	return nil
}

func (p *peripheral) ReadDescriptor(d *Descriptor) ([]byte, error) {
	rsp := p.sendReq(76, xpc.Dict{
		"kCBMsgArgDeviceUUID":       p.id,
		"kCBMsgArgDescriptorHandle": d.h,
	})
	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
		return nil, attEcode(res)
	}
	b := rsp.MustGetBytes("kCBMsgArgData")
	return b, nil
}

func (p *peripheral) WriteDescriptor(d *Descriptor, b []byte) error {
	rsp := p.sendReq(77, xpc.Dict{
		"kCBMsgArgDeviceUUID":       p.id,
		"kCBMsgArgDescriptorHandle": d.h,
		"kCBMsgArgData":             b,
	})
	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
		return attEcode(res)
	}
	return nil
}

func (p *peripheral) SetNotifyValue(c *Characteristic, f func(*Characteristic, []byte, error)) error {
	set := 1
	if f == nil {
		set = 0
	}
	// To avoid race condition, registeration is handled before requesting the server.
	if f != nil {
		// Note: when notified, core bluetooth reports characteristic handle, not value's handle.
		p.sub.subscribe(c.h, func(b []byte, err error) { f(c, b, err) })
	}
	rsp := p.sendReq(67, xpc.Dict{
		"kCBMsgArgDeviceUUID":                p.id,
		"kCBMsgArgCharacteristicHandle":      c.h,
		"kCBMsgArgCharacteristicValueHandle": c.vh,
		"kCBMsgArgState":                     set,
	})
	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
		return attEcode(res)
	}
	// To avoid race condition, unregisteration is handled after server responses.
	if f == nil {
		p.sub.unsubscribe(c.h)
	}
	return nil
}

func (p *peripheral) SetIndicateValue(c *Characteristic,
	f func(*Characteristic, []byte, error)) error {
	// TODO: Implement set indications logic for darwin (https://github.com/paypal/gatt/issues/32)
	return nil
}

func (p *peripheral) ReadRSSI() int {
	rsp := p.sendReq(43, xpc.Dict{"kCBMsgArgDeviceUUID": p.id})
	return rsp.MustGetInt("kCBMsgArgData")
}

func uuidSlice(uu []UUID) [][]byte {
	us := [][]byte{}
	for _, u := range uu {
		us = append(us, reverse(u.b))
	}
	return us
}

type message struct {
	id   int
	args xpc.Dict
	rspc chan xpc.Dict
}

func (p *peripheral) sendCmd(id int, args xpc.Dict) {
	p.reqc <- message{id: id, args: args}
}

func (p *peripheral) sendReq(id int, args xpc.Dict) xpc.Dict {
	m := message{id: id, args: args, rspc: make(chan xpc.Dict)}
	p.reqc <- m
	return <-m.rspc
}

func (p *peripheral) loop() {
	rspc := make(chan message)

	go func() {
		for {
			select {
			case req := <-p.reqc:
				p.d.sendCBMsg(req.id, req.args)
				if req.rspc == nil {
					break
				}
				m := <-rspc
				req.rspc <- m.args
			case <-p.quitc:
				return
			}
		}
	}()

	for {
		select {
		case rsp := <-p.rspc:
			// Notification
			if rsp.id == 70 && rsp.args.GetInt("kCBMsgArgIsNotification", 0) != 0 {
				// While we're notified with the value's handle, blued reports the characteristic handle.
				ch := uint16(rsp.args.MustGetInt("kCBMsgArgCharacteristicHandle"))
				b := rsp.args.MustGetBytes("kCBMsgArgData")
				f := p.sub.fn(ch)
				if f == nil {
					log.Printf("notified by unsubscribed handle")
					// FIXME: should terminate the connection?
				} else {
					go f(b, nil)
				}
				break
			}
			rspc <- rsp
		case <-p.quitc:
			return
		}
	}
}
