package gatt

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"log"
	"sync"
	"time"

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

type device struct {
	deviceHandler

	conn xpc.XPC

	role int // 1: peripheralManager (server), 0: centralManager (client)

	reqc chan message
	rspc chan message

	// Only used in client/centralManager implementation
	plist   map[string]*peripheral
	plistmu *sync.Mutex

	// Only used in server/peripheralManager implementation

	attrN int
	attrs map[int]*attr

	subscribers map[string]*central
}

func NewDevice(opts ...Option) (Device, error) {
	d := &device{
		reqc:    make(chan message),
		rspc:    make(chan message),
		plist:   map[string]*peripheral{},
		plistmu: &sync.Mutex{},

		attrN: 1,
		attrs: make(map[int]*attr),

		subscribers: make(map[string]*central),
	}
	d.Option(opts...)
	d.conn = xpc.XpcConnect("com.apple.blued", d)
	return d, nil
}

func (d *device) Init(f func(Device, State)) error {
	go d.loop()
	rsp := d.sendReq(1, xpc.Dict{
		"kCBMsgArgName":    fmt.Sprintf("gopher-%v", time.Now().Unix()),
		"kCBMsgArgOptions": xpc.Dict{"kCBInitOptionShowPowerAlert": 1},
		"kCBMsgArgType":    1,
	})
	d.stateChanged = f
	go d.stateChanged(d, State(rsp.MustGetInt("kCBMsgArgState")))
	return nil
}

func (d *device) Advertise(a *AdvPacket) error {
	// TODO
	return notImplemented
}

func (d *device) AdvertiseNameAndServices(name string, ss []UUID) error {
	us := uuidSlice(ss)
	rsp := d.sendReq(8, xpc.Dict{
		"kCBAdvDataLocalName":    name,
		"kCBAdvDataServiceUUIDs": us},
	)
	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
		return errors.New("FIXME: Advertise error")
	}
	return nil
}

func (d *device) AdvertiseIBeaconData(data []byte) error {
	var utsname xpc.Utsname
	xpc.Uname(&utsname)

	var rsp xpc.Dict

	if utsname.Release >= "14." {
		l := len(data)
		buf := bytes.NewBuffer([]byte{byte(l + 5), 0xFF, 0x4C, 0x00, 0x02, byte(l)})
		buf.Write(data)
		rsp = d.sendReq(8, xpc.Dict{"kCBAdvDataAppleMfgData": buf.Bytes()})
	} else {
		rsp = d.sendReq(8, xpc.Dict{"kCBAdvDataAppleBeaconKey": data})
	}

	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
		return errors.New("FIXME: Advertise error")
	}

	return nil
}

func (d *device) AdvertiseIBeacon(u UUID, major, minor uint16, pwr int8) error {
	b := make([]byte, 21)
	copy(b, reverse(u.b))                     // Big endian
	binary.BigEndian.PutUint16(b[16:], major) // Big endian
	binary.BigEndian.PutUint16(b[18:], minor) // Big endian
	b[20] = uint8(pwr)                        // Measured Tx Power
	return d.AdvertiseIBeaconData(b)
}

func (d *device) StopAdvertising() error {
	rsp := d.sendReq(9, nil)
	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
		return errors.New("FIXME: Stop Advertise error")
	}
	return nil
}

func (d *device) RemoveAllServices() error {
	d.sendCmd(12, nil)
	return nil
}

func (d *device) AddService(s *Service) error {
	if s.uuid.Equal(attrGAPUUID) || s.uuid.Equal(attrGATTUUID) {
		// skip GATT and GAP services
		return nil
	}

	xs := xpc.Dict{
		"kCBMsgArgAttributeID":     d.attrN,
		"kCBMsgArgAttributeIDs":    []int{},
		"kCBMsgArgCharacteristics": nil,
		"kCBMsgArgType":            1, // 1 => primary, 0 => excluded
		"kCBMsgArgUUID":            reverse(s.uuid.b),
	}
	d.attrN++

	xcs := xpc.Array{}
	for _, c := range s.Characteristics() {
		props := 0
		perm := 0
		if c.props&CharRead != 0 {
			props |= 0x02
			if CharRead&c.secure != 0 {
				perm |= 0x04
			} else {
				perm |= 0x01
			}
		}
		if c.props&CharWriteNR != 0 {
			props |= 0x04
			if c.secure&CharWriteNR != 0 {
				perm |= 0x08
			} else {
				perm |= 0x02
			}
		}
		if c.props&CharWrite != 0 {
			props |= 0x08
			if c.secure&CharWrite != 0 {
				perm |= 0x08
			} else {
				perm |= 0x02
			}
		}
		if c.props&CharNotify != 0 {
			if c.secure&CharNotify != 0 {
				props |= 0x100
			} else {
				props |= 0x10
			}
		}
		if c.props&CharIndicate != 0 {
			if c.secure&CharIndicate != 0 {
				props |= 0x200
			} else {
				props |= 0x20
			}
		}

		xc := xpc.Dict{
			"kCBMsgArgAttributeID":              d.attrN,
			"kCBMsgArgUUID":                     reverse(c.uuid.b),
			"kCBMsgArgAttributePermissions":     perm,
			"kCBMsgArgCharacteristicProperties": props,
			"kCBMsgArgData":                     c.value,
		}
		d.attrs[d.attrN] = &attr{h: uint16(d.attrN), value: c.value, pvt: c}
		d.attrN++

		xds := xpc.Array{}
		for _, d := range c.Descriptors() {
			if d.uuid.Equal(attrClientCharacteristicConfigUUID) {
				// skip CCCD
				continue
			}
			xd := xpc.Dict{
				"kCBMsgArgData": d.value,
				"kCBMsgArgUUID": reverse(d.uuid.b),
			}
			xds = append(xds, xd)
		}
		xc["kCBMsgArgDescriptors"] = xds
		xcs = append(xcs, xc)
	}
	xs["kCBMsgArgCharacteristics"] = xcs

	rsp := d.sendReq(10, xs)
	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
		return errors.New("FIXME: Add Srvice error")
	}
	return nil
}

func (d *device) SetServices(ss []*Service) error {
	d.RemoveAllServices()
	for _, s := range ss {
		d.AddService(s)
	}
	return nil
}

func (d *device) Scan(ss []UUID, dup bool) {
	args := xpc.Dict{
		"kCBMsgArgUUIDs": uuidSlice(ss),
		"kCBMsgArgOptions": xpc.Dict{
			"kCBScanOptionAllowDuplicates": map[bool]int{true: 1, false: 0}[dup],
		},
	}
	d.sendCmd(29, args)
}

func (d *device) StopScanning() {
	d.sendCmd(30, nil)
}

func (d *device) Connect(p Peripheral) {
	pp := p.(*peripheral)
	d.plist[pp.id.String()] = pp
	d.sendCmd(31,
		xpc.Dict{
			"kCBMsgArgDeviceUUID": pp.id,
			"kCBMsgArgOptions": xpc.Dict{
				"kCBConnectOptionNotifyOnDisconnection": 1,
			},
		})
}

func (d *device) respondToRequest(id int, args xpc.Dict) {

	switch id {
	case 19: // ReadRequest
		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
		t := args.MustGetInt("kCBMsgArgTransactionID")
		a := args.MustGetInt("kCBMsgArgAttributeID")
		o := args.MustGetInt("kCBMsgArgOffset")

		attr := d.attrs[a]
		v := attr.value
		if v == nil {
			c := newCentral(d, u)
			req := &ReadRequest{
				Request: Request{Central: c},
				Cap:     int(c.mtu - 1),
				Offset:  o,
			}
			rsp := newResponseWriter(int(c.mtu - 1))
			if c, ok := attr.pvt.(*Characteristic); ok {
				c.rhandler.ServeRead(rsp, req)
				v = rsp.bytes()
			}
		}

		d.sendCmd(13, xpc.Dict{
			"kCBMsgArgAttributeID":   a,
			"kCBMsgArgData":          v,
			"kCBMsgArgTransactionID": t,
			"kCBMsgArgResult":        0,
		})

	case 20: // WriteRequest
		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
		t := args.MustGetInt("kCBMsgArgTransactionID")
		a := 0
		noRsp := false
		xxws := args.MustGetArray("kCBMsgArgATTWrites")
		for _, xxw := range xxws {
			xw := xxw.(xpc.Dict)
			if a == 0 {
				a = xw.MustGetInt("kCBMsgArgAttributeID")
			}
			o := xw.MustGetInt("kCBMsgArgOffset")
			i := xw.MustGetInt("kCBMsgArgIgnoreResponse")
			b := xw.MustGetBytes("kCBMsgArgData")
			_ = o
			attr := d.attrs[a]
			c := newCentral(d, u)
			r := Request{Central: c}
			attr.pvt.(*Characteristic).whandler.ServeWrite(r, b)
			if i == 1 {
				noRsp = true
			}

		}
		if noRsp {
			break
		}
		d.sendCmd(13, xpc.Dict{
			"kCBMsgArgAttributeID":   a,
			"kCBMsgArgData":          nil,
			"kCBMsgArgTransactionID": t,
			"kCBMsgArgResult":        0,
		})

	case 21: // subscribed
		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
		a := args.MustGetInt("kCBMsgArgAttributeID")
		attr := d.attrs[a]
		c := newCentral(d, u)
		d.subscribers[u.String()] = c
		c.startNotify(attr, c.mtu)

	case 22: // unubscribed
		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
		a := args.MustGetInt("kCBMsgArgAttributeID")
		attr := d.attrs[a]
		if c := d.subscribers[u.String()]; c != nil {
			c.stopNotify(attr)
		}

	case 23: // notificationSent
	}
}

func (d *device) CancelConnection(p Peripheral) {
	d.sendCmd(32, xpc.Dict{"kCBMsgArgDeviceUUID": p.(*peripheral).id})
}

// process device events and asynchronous errors
// (implements XpcEventHandler)
func (d *device) HandleXpcEvent(event xpc.Dict, err error) {
	if err != nil {
		log.Println("error:", err)
		return
	}

	id := event.MustGetInt("kCBMsgId")
	args := event.MustGetDict("kCBMsgArgs")
	//log.Printf(">> %d, %v", id, args)

	switch id {
	case // device event
		6,  // StateChanged
		16, // AdvertisingStarted
		17, // AdvertisingStopped
		18: // ServiceAdded
		d.rspc <- message{id: id, args: args}

	case
		19, // ReadRequest
		20, // WriteRequest
		21, // Subscribe
		22, // Unubscribe
		23: // Confirmation
		d.respondToRequest(id, args)

	case 37: // PeripheralDiscovered
		xa := args.MustGetDict("kCBMsgArgAdvertisementData")
		if len(xa) == 0 {
			return
		}
		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
		a := &Advertisement{
			LocalName:        xa.GetString("kCBAdvDataLocalName", args.GetString("kCBMsgArgName", "")),
			TxPowerLevel:     xa.GetInt("kCBAdvDataTxPowerLevel", 0),
			ManufacturerData: xa.GetBytes("kCBAdvDataManufacturerData", nil),
		}

		rssi := args.MustGetInt("kCBMsgArgRssi")

		if xu, ok := xa["kCBAdvDataServiceUUIDs"]; ok {
			for _, xs := range xu.(xpc.Array) {
				s := UUID{reverse(xs.([]byte))}
				a.Services = append(a.Services, s)
			}
		}
		if xsds, ok := xa["kCBAdvDataServiceData"]; ok {
			xsd := xsds.(xpc.Array)
			for i := 0; i < len(xsd); i += 2 {
				sd := ServiceData{
					UUID: UUID{xsd[i].([]byte)},
					Data: xsd[i+1].([]byte),
				}
				a.ServiceData = append(a.ServiceData, sd)
			}
		}
		if d.peripheralDiscovered != nil {
			go d.peripheralDiscovered(&peripheral{id: xpc.UUID(u.b), d: d}, a, rssi)
		}

	case 38: // PeripheralConnected
		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
		p := &peripheral{
			id:    xpc.UUID(u.b),
			d:     d,
			reqc:  make(chan message),
			rspc:  make(chan message),
			quitc: make(chan struct{}),
			sub:   newSubscriber(),
		}
		d.plistmu.Lock()
		d.plist[u.String()] = p
		d.plistmu.Unlock()
		go p.loop()

		if d.peripheralConnected != nil {
			go d.peripheralConnected(p, nil)
		}

	case 40: // PeripheralDisconnected
		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
		d.plistmu.Lock()
		p := d.plist[u.String()]
		delete(d.plist, u.String())
		d.plistmu.Unlock()
		if d.peripheralDisconnected != nil {
			d.peripheralDisconnected(p, nil) // TODO: Get Result as error?
		}
		close(p.quitc)

	case // Peripheral events
		54, // RSSIRead
		55, // ServiceDiscovered
		62, // IncludedServiceDiscovered
		63, // CharacteristicsDiscovered
		70, // CharacteristicRead
		71, // CharacteristicWritten
		73, // NotifyValueSet
		75, // DescriptorsDiscovered
		78, // DescriptorRead
		79: // DescriptorWritten

		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
		d.plistmu.Lock()
		p := d.plist[u.String()]
		d.plistmu.Unlock()
		p.rspc <- message{id: id, args: args}

	default:
		log.Printf("Unhandled event: %#v", event)
	}
}

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

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

func (d *device) loop() {
	for req := range d.reqc {
		d.sendCBMsg(req.id, req.args)
		if req.rspc == nil {
			continue
		}
		m := <-d.rspc
		req.rspc <- m.args
	}
}

func (d *device) sendCBMsg(id int, args xpc.Dict) {
	// log.Printf("<< %d, %v", id, args)
	d.conn.Send(xpc.Dict{"kCBMsgId": id, "kCBMsgArgs": args}, false)
}
