use std::{env, fs::File};

use chisel_tuto::get_handle;
use cxxrtl::{CxxrtlHandle, CxxrtlSignal, Vcd};

struct Blink {
    pub handle: CxxrtlHandle,
    pub clk: CxxrtlSignal<1>,
    pub led: CxxrtlSignal<1>,
    pub counter: CxxrtlSignal<12>,
}

impl Blink {
    fn new() -> Self {
        let lib = concat!(env!("OUT_DIR"), "/example.so");
        let handle = get_handle(lib);
        let clk = handle.get("clk").unwrap().signal();
        let led = handle.get("led").unwrap().signal();
        let counter = handle.get("counter").unwrap().signal();
        Self {
            handle,
            clk,
            led,
            counter,
        }
    }

    fn step(&mut self) {
        self.handle.step()
    }
}

fn main() {
    let mut blink = Blink::new();
    let mut vcd = Vcd::new();
    vcd.timescale(cxxrtl::TimescaleNumber::One, cxxrtl::TimescaleUnit::Us);
    // vcd.add_without_memories(&blink.handle);
    vcd.add(&blink.handle);
    // vcd.add_if(&blink.handle, |name, obj| {
    //     dbg!(&name);
    //     dbg!(&obj);
    //     obj.r#type == CxxrtlType::Wire
    // });

    blink.step();
    let mut prev_led = false;

    let mut vcd_file = File::create("wave.vcd").unwrap();

    vcd.sample(0);
    for cycle in 0..1000 {
        blink.clk.set(false);
        blink.step();
        vcd.sample(cycle * 2);
        blink.clk.set(true);
        blink.step();
        vcd.sample(cycle * 2 + 1);
        let _counter: u16 = blink.counter.get();
        // println!("counter {counter}");
        let curr_led = blink.led.get();
        if prev_led != curr_led {
            println!("cycle {cycle}, led {curr_led}");
            prev_led = curr_led;
            // blink.counter.set(100u16);
        }

        vcd.write(&mut vcd_file).unwrap();
    }
}