//! JVM memory management: heap, stack frames, and values
//!
//! This module provides the core memory management infrastructure for JVMRS,
//! implementing the JVM specification's memory model with Rust's safety guarantees.
//!
//! # Components
//!
//! - `value` - JVM value representation (primitives, references, arrays)
//! - `frame` - Stack frame for method execution contexts
//! - `monitor` - Object synchronization and locking
//! - `heap_object` - HeapObject and HeapArray for object storage
//! - `heap` - Heap allocation with garbage collection
//! - `stack` - JVM stack for method call frames
//! - `memory_allocator` - Unified memory allocation interface
//!
//! # Memory Model
//!
//! JVMRS follows the JVM memory model:
//! - **Heap**: Stores objects and arrays (subject to garbage collection)
//! - **Stack**: Stores method frames with local variables and operand stack
//! - **Static Fields**: Per-class static field storage
//! - **Allocator**: Unified allocation strategy supporting TLAB, Arena, and direct allocation
//!
//! # Safety
//!
//! All memory operations are safe by Rust's type system:
//! - No null pointer dereferences (except explicit null checks)
//! - No use-after-free (ownership and borrowing)
//! - No data races (unless using unsafe explicitly)
//!
//! # Example
//!
//! ```rust
//! use jvmrs::memory::{Memory, Value, StackFrame, ArenaAllocator, MemoryAllocator};
//!
//! // Create memory area
//! # let mut memory = Memory::new();
//! // Create a stack frame
//! # let mut frame = StackFrame::new(10, 10, "test".to_string());
//! // Push and pop values
//! # // frame.push(Value::Int(42))?;
//! # // let value = frame.pop()?;
//! # // assert_eq!(value, Value::Int(42));
//!
//! // Use unified allocator
//! # let mut allocator = ArenaAllocator::new(1024);
//! # let obj = allocator.allocate_object("Test")?;
//! # Ok::<(), jvmrs::JvmError>(())
//! ```

mod frame;
mod heap;
mod heap_object;
mod memory_allocator;
mod monitor;
mod stack;
mod value;

use std::collections::HashMap;
use std::sync::Arc;

use crate::debug::JvmDebugger;
use crate::security::Sanitizer;

pub use frame::StackFrame;
pub use heap::Heap;
pub use heap_object::{HeapArray, HeapObject};
pub use memory_allocator::{MemoryAllocator, ArenaAllocator, TlabAllocator, MemoryType, PrimitiveArrayType, MemoryStats};
pub use monitor::Monitor;
pub use stack::JVMStack;
pub use value::Value;

/// JVM runtime memory area
#[derive(Debug)]
pub struct Memory {
    pub stack: JVMStack,
    pub heap: Heap,
    pub static_fields: HashMap<String, HashMap<String, Value>>,
}

impl Memory {
    pub fn new() -> Self {
        Memory {
            stack: JVMStack::new(),
            heap: Heap::new(),
            static_fields: HashMap::new(),
        }
    }

    pub fn with_debugger(debugger: JvmDebugger) -> Self {
        Memory {
            stack: JVMStack::new(),
            heap: Heap::with_debugger(debugger),
            static_fields: HashMap::new(),
        }
    }

    pub fn set_debugger(&mut self, debugger: JvmDebugger) {
        self.heap = Heap::with_debugger(debugger);
    }

    pub fn set_sanitizer(&mut self, sanitizer: Option<Arc<Sanitizer>>) {
        self.heap.set_sanitizer(sanitizer);
    }

    pub fn get_static(&self, class_name: &str, field_name: &str) -> Option<&Value> {
        self.static_fields
            .get(class_name)
            .and_then(|fields| fields.get(field_name))
    }

    pub fn set_static(&mut self, class_name: String, field_name: String, value: Value) {
        self.static_fields
            .entry(class_name)
            .or_insert_with(HashMap::new)
            .insert(field_name, value);
    }
}

impl Default for Memory {
    fn default() -> Self {
        Self::new()
    }
}
