import spidev
import RPi.GPIO as GPIO
from util import sleep, get_addr
from init_regs_value import init_regs_value
from regs_addr import regs_addr
CONFIG_REGS = regs_addr["CONFIG_REGS"]
STROBES = regs_addr["STROBES"]
STATUS = regs_addr["STATUS"]
MEMORY = regs_addr["MEMORY"]
MASKS = regs_addr["MASKS"]
ACCESS = regs_addr["ACCESS"]
SRES = STROBES["SRES"]
SNOP = STROBES["SNOP"]
VERSION = STATUS["VERSION"]
MARCSTATE = STATUS["MARCSTATE"]


def write_reg(spi, addr, value):
    """Write single byte to a register"""
    spi.xfer2([addr, value])
    sleep(0.1)

def read_register(spi, addr):
    READ_SINGLE = get_addr("READ_SINGLE")
    # Send address | 0x80 (read), then 0x00 dummy to clock in response
    response = spi.xfer2([READ_SINGLE | addr, 0x00])
    sleep(0.1)
    return response[1]

def spi_write_burst(spi, addr, data):
    """Write multiple bytes using burst write"""
    WRITE_BURST = get_addr("WRITE_BURST")
    tbuf = [addr | WRITE_BURST] + data
    spi.xfer2(tbuf)
    sleep(0.1)

def spi_read_burst(spi, addr, length):
    """Read multiple bytes using burst read"""
    READ_BURST = get_addr("READ_BURST")
    rbuf = [addr | READ_BURST] + [0x00] * length
    response = spi.xfer2(rbuf)
    sleep(0.1)
    return response[1:]  # Skip status byte

def strobe(spi, command):
    """Send a command strobe to CC2500"""
    spi.xfer2([command])
    sleep(0.1)

def init_cc_2500(spi):
    for reg_name, value in init_regs_value.items():
        addr = get_addr(reg_name)
        write_reg(spi, addr, value)

def setup_spi():
    spi = spidev.SpiDev()
    spi.open(0, 0)  # Bus 0, CE0 (Pin 24)
    spi.max_speed_hz = 100_000  # Safe start speed
    spi.mode = 0b00  # SPI mode 0
    return spi


def setup_gpio(GDO0_PIN=17, GDO2_PIN=27):
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(GDO0_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    GPIO.setup(GDO2_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    sleep(0.1)

def reset(spi):
    # print("Sending SRES (reset)...")
    spi.xfer2([SRES])
    sleep(0.5)

    # print("Sending SNOP (no-op)...")
    status = spi.xfer2([SNOP])[0]
    print(f"Status byte: 0x{status:02X}")

    # print("Reading MARCSTATE...")
    marc = spi.xfer2([MARCSTATE| 0x80, 0x00])[0]
    print(f"Marcstate byte: 0x{marc:02X}")

    print("Reading VERSION register...")
    version = read_register(spi, VERSION)
    print(f"CC2500 VERSION register: 0x{version:02X}")
    # if version != 0x2F:
    #     raise Exception("Expected Version was 0x0F!! Quitting")


def test_read_write_reg(spi, dbg=False):
    FIFOTHR = get_addr("FIFOTHR")
    initial_val = read_register(spi, FIFOTHR)
    test_value = initial_val + 1
    write_reg(spi, FIFOTHR, test_value)
    check = read_register(spi, FIFOTHR)
    write_reg(spi, FIFOTHR, initial_val)
    if((check != test_value) or dbg):
        print("initial value ", initial_val)
        print("test value ", test_value)
        print("check ",check)
        if(not dbg):
            raise Exception("Test Read+Write failed")        
    return check == test_value