use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
use esp_idf_sys::EspError;
use esp_idf_sys::esp;

use esp_idf_hal::rmt;
use esp_idf_hal::peripherals::Peripherals;


use std::thread::sleep;
use std::time::Duration;



fn led_tx(tx: &mut rmt::TxRmtDriver, data: &Vec<u8>) -> Result<(), EspError>  {
    use esp_idf_hal::rmt::Signal;
    use esp_idf_sys::rmt_item32_t;

    println!("abc");

    let bit1: [rmt::Pulse; 2] = [
        rmt::Pulse::new(rmt::PinState::High, rmt::PulseTicks::new(34).unwrap()),
        rmt::Pulse::new(rmt::PinState::Low,  rmt::PulseTicks::new(16).unwrap()),
    ];
                
    let bit0: [rmt::Pulse; 2] = [
        rmt::Pulse::new(rmt::PinState::High, rmt::PulseTicks::new(16).unwrap()),
        rmt::Pulse::new(rmt::PinState::Low,  rmt::PulseTicks::new(34).unwrap()),
    ];

    println!("def");
    let mut signal = rmt::VariableLengthSignal::with_capacity(data.len() * 16);
    for v in data {
            
        for i in 0..u8::BITS {
            if v & (0b1000_0000 >> i) != 0 {
                signal.push(&bit1).unwrap();
            } else {
                signal.push(&bit0).unwrap();
            }
        }
    }
        println!("ijk");
    tx.start_blocking(&signal)?;
        println!("xyz");
    Ok(())
}

fn make_color(idx: u32) -> [u8; 3] {
  let clr = (idx % 255) as u8;
  let chn = idx / 255 % 3 as u32;
  match chn % 3{
    0 => [255 - clr, clr, 0],
    1 => [0, 255 - clr, clr],
    2 => [clr, 0, 255 - clr],
    _ => todo!(),
  }
}

fn mut_color(buffer: &mut Vec<u8>, idx: usize, cdx: u32) {
  let clr = (cdx % 255) as u8;
  let chn = cdx / 255 % 3 as u32;
  match chn % 3{
    0 => {
        buffer[idx * 3    ] = 255-clr;
        buffer[idx * 3 + 1] =     clr;
        buffer[idx * 3 + 2] =       0;
    },
    1 => {
        buffer[idx * 3    ] =       0;
        buffer[idx * 3 + 1] = 255-clr;
        buffer[idx * 3 + 2] =     clr;

    },
    2 => {
        buffer[idx * 3    ] =     clr;
        buffer[idx * 3 + 1] =       0;
        buffer[idx * 3 + 2] = 255-clr;

    },
    _ => todo!(),
  }
}

fn main() {
    esp_idf_sys::link_patches();
    println!("Hello, world!");

    let config = rmt::config::TransmitConfig::new().mem_block_num(3).clock_divider(2);

    let peripherals = Peripherals::take().unwrap();
    let channel = peripherals.rmt.channel0;
    let pin = peripherals.pins.gpio9;

    // Create an RMT transmitter.
    let mut tx = rmt::TxRmtDriver::new(channel, pin, &config).unwrap();
    
    let nk:usize = 6; 
    let mut idx: Vec<Vec<u32>> = Vec::with_capacity(nk * 2 + 1);
    for i in 0..(nk * 2 + 1) {
        idx.push(Vec::with_capacity(nk * 2 + 1));
        for j in 0..(nk * 2 + 1) {
            let rsq = (i - nk).pow(2) + (j - nk).pow(2);
            let r   = (rsq as f32).sqrt() * 8f32;
            idx[i].push( r as u32  );
        }
    }

    let mut buffer = vec![0; (nk * 2 + 1).pow(2) * 3];
    loop {
      for i in 0..9945 {
        let i = i * 6;
        // let led = idx.iter().enumerate()
        //     .for_each(|(idx, cdx)|
        //         mut_color(&mut buffer, idx, cdx + (cdx - i)*6 ));
        // for ix in idx {
        //     ix.iter().enumerate()
        //     .for_each(|(idx, cdx)|
        //         mut_color(&mut buffer, idx, cdx + (cdx - i)*6 ));
        //     led_tx(&mut tx, &buffer).unwrap();
        //     sleep(Duration::from_micros(1));
        // }
        idx.iter().enumerate().for_each(|(ii, ix)| {
            let d = ii * (nk * 2 + 1);
            ix.iter().enumerate().for_each(|(ij, cdx)| {
                mut_color(&mut buffer, d + ij, cdx + (cdx - i)*6);
            });
        });
            led_tx(&mut tx, &buffer).unwrap();
            // sleep(Duration::from_micros(1));
      }
    }
       

    loop {}
}
D0D1D2D3D4D5D6D7GNDLOGIC