#!/usr/bin/env python3
"""
Open Chromatic Protocol (OCP v1.1.0) - Abstract Chromatic Ontological Engine
============================================================================
Author : Conan B. Duke (ben@droplet.is)
Origin : Metapolitik.org (Est. 2010) 3-Axis Hexadecimal Nolan Chart Replacement
         -> Ontology.to (Sociometric Semiotics @Scale)
URI    : https://dev.ontology.to/

Maps unstructured text or high-dimensional embeddings into the tensegral
Triaxial Chromatic Ontological Manifold S = [-1, 1]^3:
  - GREEN (Top   | +P / Imaginary / Perceived) <-> MAGENTA (Bottom     | -P / Vulnerability)
  - RED   (Left  | +A / Real / Embodied)       <-> CYAN    (Top-Right  | -A / Stasis)
  - BLUE  (Right | +E / Symbolic / Encoded)    <-> YELLOW  (Top-Left   | -E / Static)
"""

import hashlib
import json
import re
from typing import Dict, List, Optional, Tuple
import numpy as np


class OCPEngine:
    """
    Reference implementation of the Open Chromatic Protocol (OCP v1.1.0).
    Executes dual-tier semantic/ontological triangulation, tensegrity potential
    scoring, and deterministic 24-bit RGB/CMY Chromatic Content Descriptor (CCD)
    generation.
    """

    AUTHOR = "Conan B. Duke <ben@droplet.is>"
    ONTOLOGY_NAMESPACE = "https://dev.ontology.to/ocp/v1"
    LINEAGE_ORIGIN = "Metapolitik.org (2010) 3-Axis Hexadecimal Nolan Chart Replacement"

    def __init__(self, context_signature: Tuple[int, int, int] = (1, 1, 1)):
        # Validate and initialize the diagonal Context Signature Matrix Sigma in {-1, +1}^(3x3)
        for s in context_signature:
            if s not in (-1, 1):
                raise ValueError("Context signature elements must be strictly -1 or +1.")
        self.sigma_vec = np.array(context_signature, dtype=float)
        self.Sigma = np.diag(self.sigma_vec)

        # Canonical Tier-1 Ontological Lexicon:
        # v = [Activity/Real (A), Potency/Imaginary (P), Evaluation/Symbolic (E)] in [-1, 1]^3
        self.lexicon: Dict[str, List[float]] = {
            # RED (+A): The Real / Embodied Friction / Thermodynamic Urgency
            "detonation":   [ 0.95, -0.60, -0.80],
            "velocity":     [ 0.88,  0.45,  0.20],
            "urgent":       [ 0.85,  0.10, -0.30],
            "kinetic":      [ 0.82,  0.50,  0.15],
            "friction":     [ 0.78,  0.30, -0.10],
            "thermodynamic":[ 0.75,  0.65,  0.25],
            "outrage":      [ 0.92, -0.75, -0.88],
            "panic":        [ 0.90, -0.85, -0.82],
            # CYAN (-A): Homeostatic Stasis / Thermal Inertia
            "stasis":       [-0.95, -0.20,  0.00],
            "dormant":      [-0.88, -0.35,  0.05],
            "inert":        [-0.92, -0.50, -0.15],
            "calm":         [-0.75,  0.40,  0.80],
            "pacified":     [-0.85, -0.70,  0.65],
            # GREEN (+P): The Imaginary / Perceived Pattern / Eudaimonic Law & Stature
            "sovereign":    [-0.20,  0.92,  0.85],
            "monolithic":   [-0.45,  0.95,  0.10],
            "dominant":     [ 0.40,  0.90, -0.20],
            "fortress":     [-0.40,  0.95,  0.70],
            "eudaimonic":   [ 0.20,  0.94,  0.90],
            "tensegral":    [ 0.35,  0.92,  0.82],
            "withstood":    [ 0.25,  0.85,  0.65],
            # MAGENTA (-P): Perceived Deficit / Boundary Collapse
            "fragile":      [-0.30, -0.88, -0.25],
            "depleted":     [-0.70, -0.92, -0.60],
            "subjugated":   [-0.40, -0.95, -0.85],
            "helpless":     [ 0.35, -0.95, -0.80],
            # BLUE (+E): The Symbolic / Encoded Signal / Structural Gates
            "nourishing":   [-0.50,  0.40,  0.95],
            "syntonic":     [-0.10,  0.65,  0.92],
            "coherent":     [ 0.15,  0.75,  0.90],
            "signal":       [ 0.20,  0.70,  0.92],
            "vital":        [ 0.65,  0.80,  0.92],
            # YELLOW (-E): Symbolic Corruption / Entropic Static
            "virulent":     [ 0.60, -0.70, -0.95],
            "entropic":     [-0.30, -0.65, -0.90],
            "treacherous":  [ 0.55,  0.30, -0.95],
            "static":       [-0.20, -0.50, -0.85],
            "toxic":        [ 0.45, -0.55, -0.92],
        }

        # Syntactic operators for local window convolution
        self.negations = {"not", "never", "no", "neither", "without", "anti"}
        self.intensifiers = {"extremely": 1.5, "very": 1.3, "hyper": 1.6, "pure": 1.4, "slightly": 0.5}

    @staticmethod
    def tokenize(text: str) -> List[str]:
        """Strips punctuation and normalizes text into lowercase alphanumeric tokens."""
        return re.findall(r"\b[a-z0-9'-]+\b", text.lower())

    def get_basis_hash(self) -> str:
        """Computes the deterministic SHA-256 fingerprint of the active ontological lexicon."""
        canonical_json = json.dumps(self.lexicon, sort_keys=True).encode("utf-8")
        return hashlib.sha256(canonical_json).hexdigest()

    def compute_lexical_epa(
        self,
        text: str,
        gamma: float = 1.2,
        kappa: float = 1.5,
        window_k: int = 2,
        eta: float = 1e-8
    ) -> np.ndarray:
        """
        Tier 1: Deterministic Lexical Anchor Convolution.
        Applies salience weighting w_sal(i) = ||d_i||_2^gamma and local window operators M_i,
        followed by hyperbolic tangent bounding and Context Signature reflection Sigma.
        """
        tokens = self.tokenize(text)
        if not tokens:
            return np.zeros(3, dtype=float)

        weighted_vectors = []
        salience_weights = []

        for i, token in enumerate(tokens):
            if token in self.lexicon:
                d_i = np.array(self.lexicon[token], dtype=float)

                start_idx = max(0, i - window_k)
                preceding = tokens[start_idx:i]

                modifier = np.eye(3)
                for prev_tok in preceding:
                    if prev_tok in self.negations:
                        modifier = modifier @ np.diag([-0.5, -1.0, -1.0])
                    elif prev_tok in self.intensifiers:
                        modifier = modifier * self.intensifiers[prev_tok]

                effective_d = modifier @ d_i
                salience = (np.linalg.norm(d_i) ** gamma)

                weighted_vectors.append(salience * effective_d)
                salience_weights.append(salience)

        if not salience_weights:
            return np.zeros(3, dtype=float)

        raw_u = np.sum(weighted_vectors, axis=0) / (np.sum(salience_weights) + eta)
        v_bounded = np.tanh(kappa * raw_u)

        return self.Sigma @ v_bounded

    def lowdin_orthogonalize(self, U: np.ndarray) -> np.ndarray:
        """
        Tier 2: Symmetric Lowdin Orthogonalization.
        Given a stacked raw axis matrix U in R^(3 x d), computes W_EPA = (U U^T)^(-1/2) U
        such that W_EPA @ W_EPA^T = I_3.
        """
        if U.shape[0] != 3:
            raise ValueError(f"Expected 3 ontological rows (A, P, E), got {U.shape[0]}.")

        G = U @ U.T
        eigvals, eigvecs = np.linalg.eigh(G)

        if np.any(eigvals <= 1e-10):
            raise ValueError("Anchor axis vectors are linearly dependent; cannot orthogonalize.")

        G_inv_sqrt = eigvecs @ np.diag(1.0 / np.sqrt(eigvals)) @ eigvecs.T
        W_EPA = G_inv_sqrt @ U
        return W_EPA

    def project_embedding_tier2(
        self,
        z: np.ndarray,
        W_EPA: np.ndarray,
        z_0: Optional[np.ndarray] = None,
        tau: float = 2.0
    ) -> np.ndarray:
        """
        Projects a high-dimensional embedding vector z in R^d onto the orthonormal
        Lowdin basis W_EPA in R^(3 x d) and applies the Context Signature Matrix Sigma.
        """
        if z_0 is None:
            z_0 = np.zeros_like(z)
        v_raw = np.tanh(tau * (W_EPA @ (z - z_0)))
        return self.Sigma @ v_raw

    @staticmethod
    def compute_tensegrity_potential(
        v_epa: np.ndarray,
        f_baseline: Optional[np.ndarray] = None,
        lam: float = 1.0
    ) -> Dict[str, float]:
        """
        Computes the Ontological Tensegrity Potential Phi(v) = ||v||_2^2 + lambda * ||v - f||_2^2,
        measuring the balance between net chromatic tension and epistemic dissonance.
        """
        if f_baseline is None:
            f_baseline = np.zeros(3, dtype=float)
        chromatic_tension = float(np.dot(v_epa, v_epa))
        epistemic_dissonance = float(np.dot(v_epa - f_baseline, v_epa - f_baseline))
        phi = chromatic_tension + lam * epistemic_dissonance
        return {
            "chromatic_tension_sq": round(chromatic_tension, 4),
            "epistemic_dissonance_sq": round(epistemic_dissonance, 4),
            "tensegrity_potential_phi": round(phi, 4),
        }

    @classmethod
    def map_to_optical(cls, v_epa: np.ndarray, f_baseline: Optional[np.ndarray] = None) -> Dict:
        """
        Executes the forward affine transformations T_RGB(v) and T_CMY(v),
        8-bit quantization, spherical geometric invariants, and tensegrity metrics.
        """
        c_rgb = 0.5 * v_epa + 0.5
        c_cmy = 1.0 - c_rgb

        rgb_8bit = np.clip(np.floor(255.0 * c_rgb + 0.5), 0, 255).astype(int)
        hex_code = f"#{rgb_8bit[0]:02X}{rgb_8bit[1]:02X}{rgb_8bit[2]:02X}"

        intensity = float(np.linalg.norm(v_epa))
        u_L = np.ones(3) / np.sqrt(3.0)
        luminance_shift = float(np.dot(v_epa, u_L))
        v_perp = v_epa - luminance_shift * u_L

        tensegrity = cls.compute_tensegrity_potential(v_epa, f_baseline)

        return {
            "ontological_registers": {
                "Real_Embodied_A": round(float(v_epa[0]), 4),
                "Imaginary_Perceived_P": round(float(v_epa[1]), 4),
                "Symbolic_Encoded_E": round(float(v_epa[2]), 4),
            },
            "tensegrity_metrics": tensegrity,
            "spherical_metrics": {
                "intensity_norm": round(intensity, 4),
                "normalized_intensity": round(intensity / np.sqrt(3.0), 4),
                "luminance_projection": round(luminance_shift, 4),
                "chromatic_deviator": [round(float(x), 4) for x in v_perp],
            },
            "optical_state": {
                "rgb_norm": [round(float(x), 4) for x in c_rgb],
                "cmy_norm": [round(float(x), 4) for x in c_cmy],
                "rgb_8bit": rgb_8bit.tolist(),
                "hex": hex_code,
            },
        }

    @staticmethod
    def inverse_optical_to_epa(rgb_norm: List[float]) -> np.ndarray:
        """Inverse transformation T_RGB^(-1)(c_RGB) = 2 * c_RGB - 1_3 = c_RGB - c_CMY."""
        c_rgb = np.array(rgb_norm, dtype=float)
        return 2.0 * c_rgb - 1.0

    @staticmethod
    def bandpass_filter(v_candidate: np.ndarray, v_target: np.ndarray, epsilon: float) -> Tuple[bool, float]:
        """
        Client-side Sovereign Optical Firewall F(v_i) and Affective Deflection D(t).
        Returns (admitted_bool, squared_deflection).
        """
        diff = v_candidate - v_target
        dist = float(np.linalg.norm(diff))
        deflection_sq = dist ** 2
        return (dist <= epsilon), round(deflection_sq, 4)

    def generate_ccd(
        self,
        text: str,
        payload_cid: str = "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
        f_baseline: Optional[np.ndarray] = None
    ) -> str:
        """Compiles an immutable Chromatic Content Descriptor (CCD) JSON packet."""
        payload_sha256 = hashlib.sha256(text.encode("utf-8")).hexdigest()
        v_epa = self.compute_lexical_epa(text)
        optical_bundle = self.map_to_optical(v_epa, f_baseline=f_baseline)

        ccd = {
            "ocp_version": "1.1.0",
            "author": self.AUTHOR,
            "lineage": self.LINEAGE_ORIGIN,
            "ontology_namespace": self.ONTOLOGY_NAMESPACE,
            "payload_cid": payload_cid,
            "payload_sha256": payload_sha256,
            "basis_hash": self.get_basis_hash(),
            "context_signature": self.sigma_vec.astype(int).tolist(),
            **optical_bundle,
        }
        return json.dumps(ccd, indent=2)


if __name__ == "__main__":
    engine = OCPEngine(context_signature=(1, 1, 1))
    baseline_f = np.array([0.0, 0.20, 0.20])
    epsilon_cutoff = 0.85

    samples = [
        (
            "Ontology.to Eudaimonic Signal",
            "Tensegral and eudaimonic sovereign signal withstood thermodynamic friction, remaining coherent and vital."
        ),
        (
            "Dysphoric Outrage Static",
            "Urgent panic and virulent outrage as helpless subjects face treacherous detonation and toxic static!"
        ),
        (
            "Pacified Dissociation",
            "Calm, dormant stasis keeps the pacified and inert field motionless."
        ),
    ]

    print("=" * 78)
    print("ONTOLOGY.TO | OPEN CHROMATIC PROTOCOL (OCP v1.1.0) - ENGINE SELF-TEST")
    print("=" * 78)

    for label, sample_text in samples:
        v = engine.compute_lexical_epa(sample_text)
        admitted, deflection = engine.bandpass_filter(v, baseline_f, epsilon_cutoff)
        print(f"\n[{label}]")
        print(f"Input Text : \"{sample_text}\"")
        print(f"Firewall   : {'ADMITTED' if admitted else 'BLOCKED (Exceeds Bandpass)'} | Deflection D(t) = {deflection}")
        print(engine.generate_ccd(sample_text, f_baseline=baseline_f))