import time
import rp2
from machine import Pin, UART
from ch9120 import CH9120
import ujson
import math


# --- CH9120 Network Configuration ---
MODE = 0
LOCAL_PORT1 = 80
BAUD_RATE = 9600

# --- Init UART ---
uart1 = UART(1, baudrate=9600, tx=Pin(20), rx=Pin(21))

# --- WS2812 RGB LED Control ---
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
def ws2812():
    T1 = 2
    T2 = 5
    T3 = 3
    wrap_target()
    label("bitloop")
    out(x, 1)               .side(0)    [T3 - 1]
    jmp(not_x, "do_zero")   .side(1)    [T1 - 1]
    jmp("bitloop")          .side(1)    [T2 - 1]
    label("do_zero")
    nop()                   .side(0)    [T2 - 1]
    wrap()

sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(25))
sm.active(1)

def hsv_to_rgb(h, s, v):
    """Convert HSV to RGB (each in range 0-255)."""
    h = float(h)
    s = float(s) / 255
    v = float(v) / 255
    c = v * s
    x = c * (1 - abs((h / 60.0) % 2 - 1))
    m = v - c

    if h < 60:
        rp, gp, bp = c, x, 0
    elif h < 120:
        rp, gp, bp = x, c, 0
    elif h < 180:
        rp, gp, bp = 0, c, x
    elif h < 240:
        rp, gp, bp = 0, x, c
    elif h < 300:
        rp, gp, bp = x, 0, c
    else:
        rp, gp, bp = c, 0, x

    r = int((rp + m) * 255)
    g = int((gp + m) * 255)
    b = int((bp + m) * 255)
    return r, g, b

def load_network_config():
    try:
        with open("config.json", "r") as f:
            config = ujson.load(f)
            return (
                tuple(map(int, config["ip"].split("."))),
                tuple(map(int, config["gateway"].split("."))),
                tuple(map(int, config["subnet"].split(".")))
            )
    except Exception as e:
        print("Failed to load config, using default:", e)
        return (
            (192, 168, 0, 45),
            (192, 168, 0, 1),
            (255, 255, 255, 0)
        )

LOCAL_IP, GATEWAY, SUBNET_MASK = load_network_config()
print("Current IP:")
print(LOCAL_IP)

def save_network_config(ip, gateway, subnet):
    config = {
        "ip": ip,
        "gateway": gateway,
        "subnet": subnet
    }
    with open("config.json", "w") as f:
        ujson.dump(config, f)

def ch9120_configure():
    global uart1
    ch9120 = CH9120(uart1)
    ch9120.enter_config()
    ch9120.set_mode(MODE)
    ch9120.set_localIP(LOCAL_IP)
    ch9120.set_subnetMask(SUBNET_MASK)
    ch9120.set_gateway(GATEWAY)
    ch9120.set_localPort(LOCAL_PORT1)
    ch9120.set_baudRate(BAUD_RATE)
    ch9120.exit_config()
    uart1.read(uart1.any())
    time.sleep(0.5)
    uart1 = UART(1, baudrate=BAUD_RATE, tx=Pin(20), rx=Pin(21))
    print("CH9120 configured.")

def update_ip_configuration(ip, gateway, subnet):
    global LOCAL_IP, GATEWAY, SUBNET_MASK, uart1

    LOCAL_IP = tuple(map(int, ip.split('.')))
    GATEWAY = tuple(map(int, gateway.split('.')))
    SUBNET_MASK = tuple(map(int, subnet.split('.')))

    print("Applying new IP configuration:")
    print("IP Address:", LOCAL_IP)
    print("Gateway:", GATEWAY)
    print("Subnet Mask:", SUBNET_MASK)

    ch9120 = CH9120(uart1)
    ch9120.enter_config()
    ch9120.set_mode(MODE)
    ch9120.set_localIP(LOCAL_IP)
    ch9120.set_gateway(GATEWAY)
    ch9120.set_subnetMask(SUBNET_MASK)
    ch9120.set_localPort(LOCAL_PORT1)
    ch9120.set_baudRate(BAUD_RATE)
    ch9120.exit_config()
    uart1.read(uart1.any())
    
    uart1 = UART(1, baudrate=BAUD_RATE, tx=Pin(20), rx=Pin(21))
    ch9120 = CH9120(uart1)
    print("CH9120 reinitialized with new network settings.")
    
    save_network_config(ip, gateway, subnet)


def main():
    ch9120_configure()
    hue = 0

    while True:
        r, g, b = hsv_to_rgb(hue % 360, 255, 100)  # hue cycles 0-360
        rgb = (g << 24) | (r << 16) | (b << 8)
        sm.put(rgb)
        hue = (hue + 3) % 360  # Increase hue slowly for smoother transition
        time.sleep(0.05)

main()
