use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;

#[derive(Clone, Debug, Serialize, Deserialize)]
struct Response {
    error_message: Option<String>,
    qr_results: Option<Vec<QrResult>>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
struct QrResult {
    qr: Option<Qr>,
    error_message: Option<String>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
struct Qr {
    version: usize,
    ecc_level: u16,
    mask: u16,
    content: String,
}

#[wasm_bindgen]
pub fn decode_qr(image_bytes: &[u8]) -> String {
    let img = match image::load_from_memory(image_bytes) {
        Ok(img) => img.to_luma8(),
        Err(e) => return serde_json::to_string(
            &Response { qr_results: None, error_message: Some(format!("Parse image error: {}", e)) }
        ).unwrap(),
    };
    let mut img = rqrr::PreparedImage::prepare(img);
    let grids = img.detect_grids();

    let mut qr_results = vec![];
    for grid in grids {
        match grid.decode() {
            Err(e) => {
                qr_results.push(QrResult { qr: None, error_message: Some(format!("Parse qr error: {}", e)) })
            }
            Ok((meta, content)) => {
                qr_results.push(QrResult {
                    qr: Some(Qr {
                        version: meta.version.0,
                        ecc_level: meta.ecc_level,
                        mask: meta.mask,
                        content,
                    }),
                    error_message: None,
                })
            }
        }
    }
    serde_json::to_string(
        &Response { qr_results: Some(qr_results), error_message: None }
    ).unwrap()
}

