/// Iris Programming Language - Interpreter Module
/// 
/// Iris adalah bahasa scripting dengan paradigm hybrid:
/// - Object-oriented (prototype-based seperti JavaScript)
/// - Imperative (control flow seperti C/Rust)
/// - Functional (first-class functions, closures)

pub mod lexer;
pub mod parser;
pub mod interpreter;
pub mod value;

use std::fs;
use std::path::Path;

/// Run an Iris source file
pub fn run_file(path: &str) -> Result<(), String> {
    let source = fs::read_to_string(path)
        .map_err(|e| format!("Failed to read '{}': {}", path, e))?;
    let base = Path::new(path).parent().unwrap_or(Path::new("."));
    let file_name = Path::new(path).file_name().unwrap_or_default().to_str().unwrap_or("");
    run_with_base(&source, base.to_str().unwrap_or("."), Some(file_name))
}

/// Run Iris source code directly
pub fn run(source: &str) -> Result<(), String> {
    run_with_base(source, ".", None)
}

/// Run with base path for imports
pub fn run_with_base(source: &str, base_path: &str, entry_file: Option<&str>) -> Result<(), String> {
    let tokens = lexer::tokenize(source)?;
    let ast = parser::parse(&tokens)?;
    let mut interp = interpreter::Interpreter::new().with_base_path(base_path);
    if let Some(file) = entry_file {
        interp.mark_imported(file);
    }
    interp.execute(&ast)?;
    Ok(())
}

/// REPL - Read Eval Print Loop
pub fn repl() {
    use std::io::{self, Write};
    
    println!("Iris REPL v0.1.0");
    println!("Type 'exit' or press Ctrl+C to quit.\n");
    
    let mut interp = interpreter::Interpreter::new();
    
    loop {
        print!("iris> ");
        io::stdout().flush().unwrap();
        
        let mut input = String::new();
        if io::stdin().read_line(&mut input).is_err() {
            break;
        }
        
        let input = input.trim();
        if input == "exit" || input == "quit" {
            break;
        }
        if input.is_empty() {
            continue;
        }
        
        match lexer::tokenize(input) {
            Ok(tokens) => {
                match parser::parse(&tokens) {
                    Ok(ast) => {
                        match interp.execute(&ast) {
                            Ok(result) => {
                                if !matches!(result, value::Value::Null) {
                                    println!("{}", result);
                                }
                            }
                            Err(e) => eprintln!("Runtime error: {}", e),
                        }
                    }
                    Err(e) => eprintln!("Parse error: {}", e),
                }
            }
            Err(e) => eprintln!("Lex error: {}", e),
        }
    }
}

