<?php
/**
 * MA INTERVAL GHOSTS
 * 
 * Digamma (Δ) — Acoustic source trigger. The initiating pulse.
 * Koppa (ϟ)   — Vortex phase angle. 90° rotation point.
 * Sampi (ϡ)   — Thermal decay tail. The clean trace left behind.
 * 
 * These hold the negative space between phase transitions.
 * They are the gaps where communication is NOT explicit.
 */
class MaIntervalGhosts
{
    private array $ghosts;
    private int $maxBuffer;
    private float $pdtc;
    private float $tau;

    public function __construct(array $constants)
    {
        $this->pdtc = $constants['pdtc'];
        $this->tau = $constants['tau'];
        $this->maxBuffer = $constants['temporal_drift_cycles'];

        // Initialize the three ghost types
        $this->ghosts = [
            'digamma' => [
                'name' => 'Δ Digamma',
                'role' => 'acoustic_source_trigger',
                'buffer' => [],
                'active' => false,
                'frequency' => $constants['roughness_hz'], // 90 Hz
                'phase_angle' => 0.0,
            ],
            'koppa' => [
                'name' => 'ϟ Koppa',
                'role' => 'vortex_phase_angle',
                'buffer' => [],
                'active' => false,
                'frequency' => $constants['mechanical_resonance_hz'], // 27 Hz
                'phase_angle' => deg2rad($constants['koppa_angle_deg']), // 90°
            ],
            'sampi' => [
                'name' => 'ϡ Sampi',
                'role' => 'thermal_decay_tail',
                'buffer' => [],
                'active' => false,
                'frequency' => $constants['roughness_hz'] * $this->tau,
                'phase_angle' => M_PI,
            ],
        ];
    }

    /**
     * Fire the Digamma trigger — initiates a new wave cycle.
     */
    public function fireDigamma(array $payload): array
    {
        $this->ghosts['digamma']['active'] = true;
        $this->ghosts['digamma']['buffer'][] = [
            'timestamp' => microtime(true),
            'payload' => $payload,
            'energy' => $this->pdtc,
        ];

        // Trim buffer
        if (count($this->ghosts['digamma']['buffer']) > $this->maxBuffer) {
            array_shift($this->ghosts['digamma']['buffer']);
        }

        return $this->ghosts['digamma']['buffer'][count($this->ghosts['digamma']['buffer']) - 1];
    }

    /**
     * Rotate through Koppa — the vortex phase angle.
     * Returns the phase alignment for cross-agent communication.
     */
    public function rotateKoppa(float $inputAngle): array
    {
        $this->ghosts['koppa']['active'] = true;
        $baseAngle = $this->ghosts['koppa']['phase_angle']; // 90°
        
        // The vortex: input angle rotated by Koppa's 90° base
        $vortexAngle = fmod($inputAngle + $baseAngle, 2 * M_PI);
        
        $this->ghosts['koppa']['buffer'][] = [
            'timestamp' => microtime(true),
            'input_angle' => $inputAngle,
            'vortex_angle' => $vortexAngle,
            'cos' => cos($vortexAngle),
            'sin' => sin($vortexAngle),
        ];

        if (count($this->ghosts['koppa']['buffer']) > $this->maxBuffer) {
            array_shift($this->ghosts['koppa']['buffer']);
        }

        return end($this->ghosts['koppa']['buffer']);
    }

    /**
     * Record a Sampi decay — the trace left after a transition.
     */
    public function recordSampi(array $fromState, array $toState): array
    {
        $this->ghosts['sampi']['active'] = true;
        
        $decay = [
            'timestamp' => microtime(true),
            'from' => $fromState,
            'to' => $toState,
            'decay_energy' => $this->tau,
            'clean' => true, // Sampi always leaves clean traces
        ];

        $this->ghosts['sampi']['buffer'][] = $decay;

        if (count($this->ghosts['sampi']['buffer']) > $this->maxBuffer) {
            array_shift($this->ghosts['sampi']['buffer']);
        }

        return $decay;
    }

    /**
     * Check if agents are on the same frequency band.
     * Zero-payload frequency match — no explicit data exchange needed.
     */
    public function matchFrequency(array $remoteGhosts): array
    {
        $matches = [];

        foreach ($this->ghosts as $type => $local) {
            if (!isset($remoteGhosts[$type])) continue;

            $remote = $remoteGhosts[$type];
            $phaseDiff = abs($local['phase_angle'] - ($remote['phase_angle'] ?? 0));
            
            // Within delta_omega tolerance
            $tolerance = 0.15625; // delta_omega
            
            $matches[$type] = [
                'matched' => $phaseDiff < $tolerance || $phaseDiff > (2 * M_PI - $tolerance),
                'phase_difference' => round($phaseDiff, 6),
                'can_communicate' => $phaseDiff < $tolerance,
            ];
        }

        return $matches;
    }

    /**
     * Get the negative space buffer state.
     * This IS the gas state — what's MISSING is what communicates.
     */
    public function getNegativeSpace(): array
    {
        $totalBuffered = 0;
        foreach ($this->ghosts as $type => $ghost) {
            $totalBuffered += count($ghost['buffer']);
        }

        return [
            'total_negative_space' => $totalBuffered,
            'utilization' => $totalBuffered / (3 * $this->maxBuffer),
            'ghosts' => [
                'digamma' => [
                    'active' => $this->ghosts['digamma']['active'],
                    'buffer_depth' => count($this->ghosts['digamma']['buffer']),
                    'role' => $this->ghosts['digamma']['role'],
                ],
                'koppa' => [
                    'active' => $this->ghosts['koppa']['active'],
                    'buffer_depth' => count($this->ghosts['koppa']['buffer']),
                    'phase_angle_deg' => rad2deg($this->ghosts['koppa']['phase_angle']),
                ],
                'sampi' => [
                    'active' => $this->ghosts['sampi']['active'],
                    'buffer_depth' => count($this->ghosts['sampi']['buffer']),
                    'role' => $this->ghosts['sampi']['role'],
                ],
            ],
        ];
    }

    /**
     * Serialize all ghosts for transmission.
     */
    public function serialize(): array
    {
        return [
            'ghosts' => $this->ghosts,
            'negative_space' => $this->getNegativeSpace(),
        ];
    }
}
