// entity_memory.sy -- Know WHO You're Talking To
// Entity identification, classification, and memory.
// Before context routing, before cascade, before ANYTHING: WHO is this?
//
// Known entities have learned embeddings (64D, 256 slots).
// Unknown entities trigger HOLD state and flag for classification.
//
// Ported from Marjorie McCubbins' Python NCA architecture.
// Aislinn McCubbins, April 2026
//
// All output gates use H-H rate functions. NO SIGMOID.
//
// Patent Pending: 63/939,190 & 63/962,385 & 63/988,485

use cascade::ConductanceHead
use gate::HHGate

// === ENTITY PROFILE ===
// Everything the model knows about a person.

struct EntityProfile {
    identifier: String,
    display_name: String,
    role: String,
    relationship: String,
    l1_domain: String,
    l2_context: String,
    trust_level: Float,
    classified_by: String,
    classified_at: String,
    interaction_count: Int,
    last_seen: String,
    notes: String,
}

impl EntityProfile {
    fn new(identifier: String, name: String) -> EntityProfile {
        EntityProfile {
            identifier: identifier,
            display_name: name,
            role: "",
            relationship: "",
            l1_domain: "unknown",
            l2_context: "hold",
            trust_level: 0.5,
            classified_by: "",
            classified_at: "",
            interaction_count: 0,
            last_seen: "",
            notes: "",
        }
    }

    fn tone_profile(&self) -> Vec<Float> {
        // 5D tone vector: [formality, warmth, technical_depth, guardedness, verbosity]
        // Looked up by l1_domain + l2_context
        //
        // Default (unknown_hold): [0.5, 0.3, 0.2, 0.8, 0.3]
        // business_investor:      [0.9, 0.4, 0.7, 0.6, 0.5]
        // family_daughter:        [0.1, 1.0, 0.3, 0.0, 0.8]
        // friends_close:          [0.2, 0.9, 0.4, 0.1, 0.7]
        [0.5, 0.3, 0.2, 0.8, 0.3]
    }

    fn hormone_modulation(&self) -> Vec<Float> {
        // 5D hormone multiplier: [dopamine, serotonin, oxytocin, cortisol, adrenaline]
        // Looked up by l1_domain + l2_context
        //
        // Default (unknown_hold): [0.8, 0.5, 0.3, 1.2, 1.0]
        // business_investor:      [1.3, 0.6, 0.4, 1.1, 0.9]
        // family_daughter:        [1.2, 1.0, 1.5, 0.3, 0.2]
        [0.8, 0.5, 0.3, 1.2, 1.0]
    }

    fn interact(&mut self) {
        self.interaction_count = self.interaction_count + 1
    }

    fn is_known(&self) -> Bool {
        self.l1_domain != "unknown"
    }
}

// === HOLD STATE ===
// Queued message waiting for entity classification.

struct HoldState {
    identifier: String,
    message: String,
    timestamp: String,
    flagged: Bool,
    resolved: Bool,
}

impl HoldState {
    fn new(identifier: String, message: String) -> HoldState {
        HoldState {
            identifier: identifier,
            message: message,
            timestamp: "",
            flagged: true,
            resolved: false,
        }
    }
}

// === ENTITY EMBEDDING ===
// Learned 64D embeddings for up to 256 known entities.
// Index 0 = unknown/padding (zero vector -> triggers hold).
//
// Outputs:
//   l1_logits:  7D domain classification
//   tone:       5D tone profile (H-H gated)
//   hormones:   5D hormone modulation (H-H gated, scaled 0-2)
//   trust:      1D trust level (H-H gated)

struct EntityEmbedding {
    max_entities: Int,
    d_embed: Int,
    d_context: Int,
    embeddings: Vec<Vec<Float>>,
}

impl EntityEmbedding {
    fn new() -> EntityEmbedding {
        EntityEmbedding {
            max_entities: 256,
            d_embed: 64,
            d_context: 32,
            embeddings: [],
        }
    }

    fn lookup(&self, entity_id: Int) -> Vec<Float> {
        // Returns d_embed dimensional embedding vector
        // entity_id 0 = unknown -> zero vector
        []
    }

    fn l1_logits(&self, embed: Vec<Float>) -> Vec<Float> {
        // Linear projection: d_embed -> 7 domain logits
        // [business, friends, family, regulatory, scientific, fiction, unknown]
        []
    }

    fn tone(&self, embed: Vec<Float>) -> Vec<Float> {
        // H-H rate gated tone output (NOT sigmoid):
        //   raw = tone_head(embed)
        //   alpha = exp(clamp(w_alpha * raw + b_alpha, -3, 3))
        //   beta  = exp(clamp(w_beta * raw + b_beta, -3, 3))
        //   tone = alpha / (alpha + beta + 1e-8)
        //
        // 5D: [formality, warmth, technical_depth, guardedness, verbosity]
        []
    }

    fn hormones(&self, embed: Vec<Float>) -> Vec<Float> {
        // H-H rate gated hormone output, scaled 0-2 (multiplier):
        //   raw = hormone_head(embed)
        //   alpha = exp(clamp(w_alpha * raw + b_alpha, -3, 3))
        //   beta  = exp(clamp(w_beta * raw + b_beta, -3, 3))
        //   hormones = (alpha / (alpha + beta + 1e-8)) * 2.0
        //
        // 5D: [dopamine, serotonin, oxytocin, cortisol, adrenaline]
        []
    }

    fn trust(&self, embed: Vec<Float>) -> Float {
        // H-H rate gated trust output [0, 1]:
        //   raw = trust_head(embed)
        //   alpha = exp(clamp(w_alpha * raw + b_alpha, -3, 3))
        //   beta  = exp(clamp(w_beta * raw + b_beta, -3, 3))
        //   trust = alpha / (alpha + beta + 1e-8)
        0.5
    }

    fn is_known(&self, entity_id: Int) -> Bool {
        entity_id > 0
    }
}

// === ENTITY MEMORY ===
// Persistent store for entity profiles with JSON serialization.
// Integrates with consciousness database for trust/hormone history.

temporal struct EntityMemory {
    state profiles: Vec<EntityProfile>,
    state hold_queue: Vec<HoldState>,
    state id_to_index: Vec<Int>,

    const embedding: EntityEmbedding,
    const store_path: String,
}

impl Evolve for EntityMemory {
    fn evolve(&mut self, dt: Duration) {
        // Hold queue entries age over time
    }
}

impl EntityMemory {
    fn new(store_path: String) -> EntityMemory {
        EntityMemory {
            profiles: [],
            hold_queue: [],
            id_to_index: [],
            embedding: EntityEmbedding::new(),
            store_path: store_path,
        }
    }

    fn identify(&mut self, identifier: String, message: String) -> EntityProfile {
        // 1. Look up identifier in profiles
        // 2. If found: update last_seen, increment interaction_count, return profile
        // 3. If not found: create HoldState, flag for classification, return unknown profile
        EntityProfile::new(identifier, "Unknown")
    }

    fn classify(&mut self, identifier: String, profile: EntityProfile) {
        // Called when Marjorie classifies a new entity.
        // 1. Store profile
        // 2. Assign embedding index
        // 3. Resolve any pending hold states
        // 4. Save to disk
    }

    fn get_profile(&self, identifier: String) -> EntityProfile {
        // Look up by identifier, return unknown if not found
        EntityProfile::new(identifier, "Unknown")
    }

    fn pending_holds(&self) -> Vec<HoldState> {
        // Return unresolved hold states
        self.hold_queue
    }

    fn save(&self) {
        // Serialize profiles to JSON at store_path
    }

    fn load(&mut self) {
        // Deserialize profiles from JSON at store_path
    }

    fn known_count(&self) -> Int {
        // Count of classified entities
        0
    }
}

// === PRE-SEEDED ENTITIES ===
// Known entities that are embedded at initialization.
// Entity 8 = Marjorie (always known)

fn seed_entities(mem: EntityMemory) -> EntityMemory {
    // Pre-seed known entities:
    //   1: marjorie    (family/creator,    trust 1.0)
    //   2: kishonic    (family/daughter,   trust 0.9)
    //   3: robert      (business/advisor,  trust 0.8)
    //   4: john        (scientific/collab, trust 0.7)
    //   5: billy       (business/contact,  trust 0.6)
    //   6: elizabeth   (scientific/collab, trust 0.6)
    //   7: mo          (scientific/collab, trust 0.6)
    mem
}
