use hermes_rs::array_parser::ArrayTypes;
use hermes_rs::hermes_file::HermesFile;
use std::io::{self};
use std::{env, fs::File};

fn main() {
    // Get first parameter passed to the program
    let args: Vec<String> = env::args().collect();
    let hbc_file = &args[1];

    if args.len() < 2 {
        println!("Usage: strings <hbc_file>");
        std::process::exit(1);
    }

    // check if file exists
    if !std::path::Path::new(hbc_file).exists() {
        println!("File not found: {}", hbc_file);
        std::process::exit(1);
    }

    let f = File::open(hbc_file).expect("no file found");

    let mut reader = io::BufReader::new(f);

    fn print_array_vals(
        hermes_file: &HermesFile<&mut io::BufReader<File>>,
        next_idx: usize,
        array_vals: &Vec<ArrayTypes>,
    ) {
        let mut js_values: Vec<String> = Vec::new();
        for arr_val in array_vals {
            let v = match arr_val {
                ArrayTypes::NullValue {} => {
                    // JS null
                    "null".to_string()
                }
                ArrayTypes::TrueValue { value: true } => {
                    // JS true
                    "true".to_string()
                }
                ArrayTypes::FalseValue { value: false } => {
                    // JS false
                    "false".to_string()
                }
                ArrayTypes::NumberValue { value: val } => {
                    // JS number
                    format!("{}", val)
                }
                ArrayTypes::LongStringValue { value: val } => {
                    // JS string literal, quoted
                    let s = hermes_file.get_string_from_storage_by_index(*val as usize);
                    format!("{:?}", s)
                }
                ArrayTypes::ShortStringValue { value: val } => {
                    let s = hermes_file.get_string_from_storage_by_index(*val as usize);
                    format!("{:?}", s)
                }
                ArrayTypes::ByteStringValue { value: val } => {
                    let s = hermes_file.get_string_from_storage_by_index(*val as usize);
                    format!("{:?}", s)
                }
                ArrayTypes::IntegerValue { value: val } => {
                    // JS number
                    format!("{}", val)
                }
                _ => {
                    // fallback: JS undefined
                    "undefined".to_string()
                }
            };
            js_values.push(v);
        }
        // Print as a JS array
        println!("const arr_{} = [{}];", next_idx, js_values.join(", "));
    }

    let mut hermes_file: HermesFile<&mut io::BufReader<File>> =
        HermesFile::deserialize(&mut reader);

    let mut next_idx = 0;
    while next_idx < hermes_file.array_buffer_storage.len() {
        let o = hermes_file.get_array_buffer(next_idx, 0);
        let new_idx = o.0;
        print_array_vals(&hermes_file, new_idx, &o.1);
        if new_idx <= next_idx {
            println!("Warning: Index didn't advance, breaking to prevent infinite loop");
            break;
        }

        next_idx = new_idx;
    }

    // println!("{:?} = {:?}",next_idx, array_vals);
    // while next_idx < hermes_file.array_buffer_storage.len() {
    //     let (next_idx, array_vals) = hermes_file.get_array_buffer(next_idx, 0);
    //     print_array_vals(&hermes_file, next_idx, &array_vals);
    // }
}
