package comms

import (
	"bytes"
	"encoding/binary"
	"math"
	"odoki-firmware/constants"
	"odoki-firmware/utils"
	"time"

	"tinygo.org/x/bluetooth"
)

var adapter = bluetooth.DefaultAdapter

var heartRateMeasurement bluetooth.Characteristic

var rawDataChra bluetooth.Characteristic

func Init() {
	// Enable BLE interface.
	utils.CheckError(adapter.Enable())

	// Define the peripheral device info.
	adv := adapter.DefaultAdvertisement()
	address, err := adapter.Address()
	address_str := address.MAC.String()
	utils.CheckError(err)
	utils.CheckError(adv.Configure(bluetooth.AdvertisementOptions{
		LocalName:    "odoki " + address_str[0:2] + address_str[3:5],
		ServiceUUIDs: []bluetooth.UUID{bluetooth.ServiceUUIDHeartRate},
	}))

	// Start advertising
	utils.CheckError(adv.Start())
	println("advertising...")

	utils.CheckError(adapter.AddService(&bluetooth.Service{
		UUID: bluetooth.ServiceUUIDHeartRate,
		Characteristics: []bluetooth.CharacteristicConfig{
			{
				Handle: &heartRateMeasurement,
				UUID:   bluetooth.CharacteristicUUIDHeartRateMeasurement,
				Value:  []byte{0, 0}, //default value is 0
				Flags:  bluetooth.CharacteristicNotifyPermission,
			},
		},
	}))

	defaultValue := make([]byte, (constants.ChannelCount)*4+1)
	utils.CheckError(adapter.AddService(&bluetooth.Service{
		UUID: bluetooth.ServiceUUIDAdafruitAddressable,
		Characteristics: []bluetooth.CharacteristicConfig{
			{
				Handle: &rawDataChra,
				UUID:   bluetooth.CharacteristicUUIDAdafruitRawTXRX,
				Value:  defaultValue,
				Flags:  bluetooth.CharacteristicNotifyPermission,
			},
		},
	}))

}

func UpdateHR(heartRate uint8) {
	heartRateMeasurement.Write([]byte{0, heartRate})
}

func SimulateHR() {
	var heartRate uint8 = 60
	nextBeat := time.Now()
	for {
		nextBeat = nextBeat.Add(time.Minute / time.Duration(heartRate))
		println("tick", time.Now().Format("04:05.000"))
		time.Sleep(time.Until(nextBeat))

		// random variation in heartrate
		heartRate = utils.RandomInt(65, 85)

		// and push the next notification
		heartRateMeasurement.Write([]byte{0, heartRate})
	}
}

func WriteECG(value int32) {
	//data := []byte{0}
	/*
		buffer := new(bytes.Buffer)

		for i := 0; i < constants.ChannelCount; i++ {
			binary.Write(buffer, binary.BigEndian, value)
		}

		data = append(data, buffer.Bytes()...)
	*/
	//rawDataChra.Write(data)
}

func SimulateECG() {
	k := 0.0
	for {
		data := []byte{0}

		buffer := new(bytes.Buffer)

		for i := 0; i < constants.ChannelCount; i++ {
			value := int32(math.Sin(k) * 10000)
			binary.Write(buffer, binary.BigEndian, value)
		}

		data = append(data, buffer.Bytes()...)

		rawDataChra.Write(data)
		time.Sleep(time.Millisecond * 100)
		k += 0.1
	}

}
