package ads1293

import (
	"time"

	"tinygo.org/x/drivers"

	"machine"
)

// Device holds the already configured I2C bus and the address of the sensor.
type Device struct {
	DrdyPin machine.Pin
	csPin   machine.Pin
	spiBus  drivers.SPI
}

// Config is the configuration for the ADS1293.
type Config struct {
	DrdyPin machine.Pin
	CsPin   machine.Pin
	SPIBus  drivers.SPI
}

func New(config Config) Device {
	return Device{DrdyPin: config.DrdyPin, csPin: config.CsPin, spiBus: config.SPIBus}
}

func (d *Device) GetECGdata(channel uint8) int32 {
	var rawData [3]uint8
	var ecgData int32

	if channel < 1 || channel > 3 {
		return -1 //return error, -1
	} else {
		channel -= 1
	}

	rawData[0] = d.ads1293ReadRegister(0x37 + (channel * 3))
	rawData[1] = d.ads1293ReadRegister(0x38 + (channel * 3))
	rawData[2] = d.ads1293ReadRegister(0x39 + (channel * 3))

	var tempData uint32 = uint32(rawData[0]) << 16
	tempData += uint32(rawData[1]) << 8
	tempData += uint32(rawData[2])
	tempData = tempData << 8
	ecgData = int32(tempData)

	return ecgData
}

func (d *Device) SetAds1293Pins() {
	d.DrdyPin.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
	d.csPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
}

func (d *Device) Ads1293Begin3LeadECG() {
	d.ads1293WriteRegister(CONFIG, 0x00)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(FLEX_CH1_CN, 0x11)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(FLEX_CH2_CN, 0x19)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(CMDET_EN, 0x07)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(RLD_CN, 0x04)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(OSC_CN, 0x04)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(AFE_SHDN_CN, 0x24)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(R2_RATE, 0x02)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(R3_RATE_CH1, 0x02)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(R3_RATE_CH2, 0x02)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(DRDYB_SRC, 0x08)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(CH_CNFG, 0x30)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(CONFIG, 0x01)
	time.Sleep(1 * time.Millisecond)
}

func (d *Device) Ads1293Begin5LeadECG() {

	//channel 1 cn
	d.ads1293WriteRegister(0x01, 0x11)
	time.Sleep(1 * time.Millisecond)

	//channel2
	d.ads1293WriteRegister(0x02, 0x19)
	time.Sleep(1 * time.Millisecond)

	///channel3 cn
	d.ads1293WriteRegister(0x03, 0x2e)
	time.Sleep(1 * time.Millisecond)

	//Common-Mode Detection and Right-Leg Drive Common-Mode Feedback Control Register
	d.ads1293WriteRegister(0x0a, 0x07)
	time.Sleep(1 * time.Millisecond)

	//RLD control
	d.ads1293WriteRegister(0x0c, 0x04)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(0x0d, 0x01)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(0x0e, 0x02)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(0x0f, 0x03) //0000 0011
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(0x10, 0x01)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(0x12, 0x04)
	time.Sleep(1 * time.Millisecond)

	//debug
	// d.ads1293WriteRegister(0x13, 0x07);
	time.Sleep(1 * time.Millisecond)

	//debug
	d.ads1293WriteRegister(0x14, 0x00)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(0x21, 0x02)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(0x22, 0x02)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(0x23, 0x02)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(0x24, 0x02)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(0x27, 0x08)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(0x2f, 0x70)
	time.Sleep(1 * time.Millisecond)

	d.ads1293WriteRegister(00, 0x01)
	time.Sleep(1 * time.Millisecond)
}

func (d *Device) ads1293WriteRegister(wrAddress uint8, data uint8) {

	var dataToSend uint8 = (wrAddress & WREG)
	d.csPin.Low()
	d.spiBus.Transfer(dataToSend)
	d.spiBus.Transfer(data)
	d.csPin.High()
}

func (d *Device) ads1293ReadRegister(rdAddress uint8) uint8 {

	var rdData uint8
	var dataToSend uint8 = (rdAddress | RREG)
	d.csPin.Low()
	d.spiBus.Transfer(dataToSend)
	rdData, _ = d.spiBus.Transfer(0)
	d.csPin.High()

	return rdData
}

func (d *Device) ReadSensorID() (uint8, bool) {

	var ID uint8 = 0xff
	ID = d.ads1293ReadRegister(REVID)
	println(ID)
	if ID != 0xff {
		return ID, true
	} else {
		return ID, false
	}
}

func (d *Device) configDCleadoffDetect() {

}

func (d *Device) configACleadoffDetect() {

}

func (d *Device) setSamplingRate() {

}

func (d *Device) DisableCh1() {
	d.ads1293WriteRegister(FLEX_CH1_CN, 0x00)
	time.Sleep(1 * time.Millisecond)
}

func (d *Device) DisableFilterAllChannels() {
	d.ads1293WriteRegister(DIS_EFILTER, 0x07)
	time.Sleep(1 * time.Millisecond)
}

func (d *Device) DisableFilter(channel uint8) bool {

	if channel > 3 || channel < 0 {
		println("Wrong channel error!")
		return false
	}

	var channelBitMask uint8 = 0x01
	channelBitMask = channelBitMask << (channel - 1)
	d.ads1293WriteRegister(DIS_EFILTER, channelBitMask)
	time.Sleep(1 * time.Millisecond)
	return true
}

func (d *Device) readErrorStatus() uint8 {

	return d.ads1293ReadRegister(ERR_STATUS)
}

func (d *Device) attachTestSignal(channel uint8, pol uint8) bool {

	if (channel > 3) || (channel < 1) {
		println("Wrong channel error!")
		return false
	}

	pol = (pol << 6)
	d.ads1293WriteRegister(channel, pol)
	time.Sleep(1 * time.Millisecond)

	return true
}

func (d *Device) ReadChannelsIfReady() (ready bool, ecgCh1, ecgCh2, ecgCh3 int32) {
	if !d.DrdyPin.Get() {
		return true, d.GetECGdata(1), d.GetECGdata(2), d.GetECGdata(3)
	}
	return false, 0, 0, 0
}
