package pcb

import (
	"sync"
	"th7/data/pcb"

	"github.com/stianeikeland/go-rpio/v4"
)

type TH7Adapter struct {
	mu    sync.Mutex
	table pcb.Table
}

func NewTH7Adapter() (*TH7Adapter, error) {

	var adapter TH7Adapter

	err := rpio.Open()
	if err != nil {
		return &adapter, err
	}

	err = rpio.SpiBegin(rpio.Spi0)
	if err != nil {
		return &adapter, err
	}

	return &adapter, nil
}

func (t *TH7Adapter) Deinit() error {
	rpio.SpiEnd(rpio.Spi0)
	return rpio.Close()
}

func (t *TH7Adapter) UpdateTable() {
	var newTable pcb.Table
	var cb1, cb2 byte

	rpio.SpiChipSelect(0) //CE0

	// command bytes
	cb1 = 4 + 2 + ((0 & 4) >> 2)
	cb2 = ((0 & 3) << 6)

	buffer := []byte{cb1, cb2, 0x00}

	rpio.SpiExchange(buffer)

	newTable.Vref = float64(buffer[1])*256.0 + float64(buffer[2]) //TODO: fix
	//newTable.Vref = float64(int(buffer[1])<<8 | int(buffer[2]))
	newTable.Vadj = newTable.Vref / 3355.4432
	newTable.Pivdd = 5.0 / newTable.Vadj

	t.mu.Lock()
	defer t.mu.Unlock()

	t.table = newTable
}

func (t *TH7Adapter) GetTable() pcb.Table {
	t.mu.Lock()
	defer t.mu.Unlock()

	return t.table
}

func (t *TH7Adapter) ReadChannel(id int, gain float64) float64 {

	table := t.GetTable()
	channel := byte(id)
	var ch, perfect, big_v, uv float64
	var cb1, cb2 byte

	rpio.SpiChipSelect(0) // CE0

	// command bytes
	cb1 = 4 + 2 + ((channel & 4) >> 2)
	cb2 = ((channel & 3) << 6)

	buffer := []byte{cb1, cb2, 0x00}

	rpio.SpiExchange(buffer)

	ch = float64(buffer[1])*256.0 + float64(buffer[2])
	perfect = ((table.Vref - ch) * table.Vadj)
	big_v = (perfect / 4096.0) * 5.0
	uv = big_v * 100 * gain

	return uv
}

func (t *TH7Adapter) ReadPCBTemp() float64 {
	rpio.SpiChipSelect(1) // CE1
	buffer := []byte{0x00, 0x00, 0x00, 0x00}
	rpio.SpiExchange(buffer)

	var pcb_temp, number float64

	number = float64(buffer[0])*256.0 + float64(buffer[1])
	//(number/8)*(1/16) == (number/(8*16)) == number/128 == number >> 7 ?
	pcb_temp = (number / 8.0) * 0.0625
	return pcb_temp
}