//! Template project for Rust on ESP32 (`no_std`) based on [`esp-hal`](https://github.com/esp-rs/esp-hal)
//!
//! Useful resources:
//! - [The Rust on ESP Book](https://docs.esp-rs.org/book/)
//! - [Embedded Rust (no_std) on Espressif](https://docs.esp-rs.org/no_std-training/)
//! - [Matrix channel](https://matrix.to/#/#esp-rs:matrix.org)

#![no_std]
#![no_main]

use esp_idf_svc::hal::{delay::Delay, gpio::*};
use esp_idf_svc::sys::esp;
use esp_println::println;
use std::thread;
use std::time::Duration;

const MPU6050_ADDRESS: u8 = 0x68;
const ACCEL_XOUT_H: u8 = 0x3B;
const PWR_MGMT_1: u8 = 0x6B;

#[no_mangle]
fn main() -> ! {
    unsafe {
        esp_idf_svc::sys::esp_app_desc_t {
            magic_word: esp_idf_svc::sys::ESP_APP_DESC_MAGIC_WORD,
            version: b"1\0".as_ptr() as *const _,
            project_name: b"HAR_Project\0".as_ptr() as *const _,
            idf_ver: esp_idf_svc::sys::esp_idf_get_version() as *const _,
            time: b"TIME\0".as_ptr() as *const _,
            date: b"DATE\0".as_ptr() as *const _,
            sha256: [0u8; 32],
        };
    }

    esp_idf_svc::sys::esp!(esp_idf_svc::sys::esp_wifi_set_mode(
        esp_idf_svc::sys::wifi_mode_t_WIFI_MODE_STA
    ))
    .unwrap();

    println!("HAR Project - MPU6050 Data");

    let peripherals = esp_idf_svc::hal::peripherals::Peripherals::take().unwrap();
    let sda = peripherals.pins.gpio21.into_output().unwrap(); // Example SDA pin
    let scl = peripherals.pins.gpio22.into_output().unwrap(); // Example SCL pin

    let config = esp_idf_svc::hal::i2c::config::Config::new().baudrate(100_kHz.into());
    let mut i2c = esp_idf_svc::hal::i2c::I2cDriver::new(
        peripherals.i2c0,
        sda.into_input_output().unwrap(),
        scl.into_input_output().unwrap(),
        &config,
    )
    .unwrap();

    // Wake up the MPU6050
    i2c.write(MPU6050_ADDRESS, &[PWR_MGMT_1, 0x00], Duration::from_millis(100))
        .unwrap();
    Delay::new(&()).delay_ms(100);

    loop {
        let mut accel_data = [0u8; 6];
        match i2c.read(
            MPU6050_ADDRESS,
            ACCEL_XOUT_H,
            &mut accel_data,
            Duration::from_millis(100),
        ) {
            Ok(_) => {
                let acc_x = (accel_data[0] as i16) << 8 | (accel_data[1] as i16);
                let acc_y = (accel_data[2] as i16) << 8 | (accel_data[3] as i16);
                let acc_z = (accel_data[4] as i16) << 8 | (accel_data[5] as i16);

                println!("Raw Accel X: {}", acc_x);
                println!("Raw Accel Y: {}", acc_y);
                println!("Raw Accel Z: {}", acc_z);

                // --- HAR Logic Simulation (Replace with your actual HAR code) ---
                // In a real HAR project, you would:
                // 1. Preprocess this raw data (e.g., filtering).
                // 2. Extract features from a window of data (e.g., mean, std dev, magnitude).
                // 3. Classify the activity based on these features (e.g., using thresholds or a simple ML model).

                // For this basic example, let's just simulate a simple activity detection
                let acceleration_magnitude_sq =
                    (acc_x as f32).powi(2) + (acc_y as f32).powi(2) + (acc_z as f32).powi(2);
                let acceleration_magnitude = acceleration_magnitude_sq.sqrt();

                if acceleration_magnitude > 5000.0 {
                    println!("Activity Detected (Simulated)");
                } else {
                    println!("Idle (Simulated)");
                }
                // --- End of HAR Logic Simulation ---
            }
            Err(e) => println!("Error reading MPU6050: {:?}", e),
        }

        thread::sleep(Duration::from_millis(500));
    }
}