use std::io::Result;

pub trait RtlDevice {
  /// Send a control message to the device
  fn control_send(&mut self, b_request: u8, data: &[u8]) -> Result<()>;
  /// Receive a control message from a device
  fn control_recv(&mut self, b_request: u8, length: usize) -> Result<Vec<u8>>;
  /// Read a chunk of raw IQ samples from the bulk-in endpoint
  ///
  /// # Arguments
  /// * `buffer` - the slice to fill with received data
  ///
  /// # Returns
  /// Number of bytes actually read
  fn read_bulk(&mut self, buffer: &mut [u8]) -> Result<usize>;
}

pub fn run<S: RtlDevice>(device: &mut S) -> Result<()> {
  // RESET
  device.control_send(0x00, &[])?;
  // SET_FREQ
  device.control_send(0x02, &1_090_000_000u32.to_le_bytes())?;
  // SET_SR
  device.control_send(0x03, &2_400_000u32.to_le_bytes())?;
  // AGC on
  device.control_send(0x04, &[1])?;

  // Precompute the preamble pattern in “half‐bit” units (16 samples)
  let preamble_halfbit_pattern = [
    1,1, 0,0, 1,1, 0,0,
    1,1, 0,0, 0,0, 0,0
  ];

  // Create a big buffer to hold raw I/Q bytes
  let mut iq_buffer = [0u8; 16_384];

  loop {
    // Read one bulk transfer's worth of I/Q data
    let bytes_read = device.read_bulk(&mut iq_buffer)?;
    if bytes_read < 32 {
      // Must be at least 16 I/Q pairs
      continue;
    }

    let raw = &iq_buffer[..bytes_read];

    // Build a vector of "bit-samples" by thresholding I
    // raw is [I0,Q0,I1,Q1,...], so step by 2
    let mut halfbit_samples = Vec::with_capacity(raw.len() / 2);
    for pair in raw.chunks_exact(2) {
      let i_sample = pair[0] as u16;
      // Threshold at 200
      halfbit_samples.push(if i_sample > 200 {
        1
      } else {
        0
      });
    }

    // Scan for the 16-sample preamble
    let mut data_start_index = None;
    for idx in 0..halfbit_samples.len().saturating_sub(16) {
      if &halfbit_samples[idx..idx + 16] == preamble_halfbit_pattern {
        data_start_index = Some(idx + 16);
        break;
      }
    }

    let data_start = match data_start_index {
      Some(i) => i,
      None => continue // No preamble found in this chunk
    };

    // Collect 112 ADS-B bits, each manchester-encoded into 2 half-bits
    // 224 half-bit samples total
    let required_samples = 112 * 2;
    if data_start + required_samples > halfbit_samples.len() {
      // Not enough in this buffer
      continue;
    }
    let manchester_slice = &halfbit_samples[data_start..data_start + required_samples];

    // Manchester-decode pairs back into plain bits
    let mut adsb_bits = Vec::with_capacity(112);
    for window in manchester_slice.chunks_exact(2) {
      match window {
        [1, 0] => adsb_bits.push(0),
        [0, 1] => adsb_bits.push(1),
        _ => {
          // Failed manchester pattern
          adsb_bits.clear();
          break;
        }
      }
    }

    if adsb_bits.len() != 112 {
      // Data is malformed
      continue;
    }

    // Pack 112 bits into 14 bytes (MSB first in each byte)
    let mut adsb_payload = [0u8; 14];
    for (bit_index, &bit_value) in adsb_bits.iter().enumerate() {
      let byte_index = bit_index / 8;
      let bit_in_byte = 7 - (bit_index % 8);
      if bit_value == 1 {
        adsb_payload[byte_index] |= 1 << bit_in_byte;
      }
    }

    // Print out the 14-byte payload in hex
    print!("ADS-B payload: ");
    for byte in &adsb_payload {
      print!("{:02X} ", byte);
    }
    println!();
  }
}