<?php
require_once 'db.php';

$clients = [];
$meetings = [];

$address = '0.0.0.0';
$port = 8080;

$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($server, $address, $port);
socket_listen($server);

echo "WebSocket server démarré sur ws://$address:$port\n";

while (true) {
    $read = array_merge([$server], $clients);
    $write = null;
    $except = null;
    
    socket_select($read, $write, $except, 0, 10);
    
    if (in_array($server, $read)) {
        $client = socket_accept($server);
        $clients[] = $client;
        
        $header = socket_read($client, 1024);
        performHandshake($header, $client, $address, $port);
        
        socket_getpeername($client, $ip);
        echo "Nouvelle connexion: $ip\n";
        
        unset($read[array_search($server, $read)]);
    }
    
    foreach ($read as $client) {
        $data = @socket_read($client, 1024, PHP_BINARY_READ);
        
        if ($data === false) {
            $index = array_search($client, $clients);
            unset($clients[$index]);
            socket_close($client);
            echo "Client déconnecté\n";
            continue;
        }
        
        $message = unmask($data);
        if ($message) {
            $json = json_decode($message, true);
            handleMessage($json, $client, $clients, $meetings);
        }
    }
}

socket_close($server);

function performHandshake($headers, $client, $address, $port) {
    $lines = explode("\n", $headers);
    $key = '';
    
    foreach ($lines as $line) {
        if (preg_match('/Sec-WebSocket-Key: (.*)/', $line, $match)) {
            $key = trim($match[1]);
            break;
        }
    }
    
    $acceptKey = base64_encode(pack('H*', sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
    
    $response = "HTTP/1.1 101 Switching Protocols\r\n";
    $response .= "Upgrade: websocket\r\n";
    $response .= "Connection: Upgrade\r\n";
    $response .= "Sec-WebSocket-Accept: $acceptKey\r\n\r\n";
    
    socket_write($client, $response);
}

function unmask($payload) {
    $length = ord($payload[1]) & 127;
    
    if ($length == 126) {
        $masks = substr($payload, 4, 4);
        $data = substr($payload, 8);
    } elseif ($length == 127) {
        $masks = substr($payload, 10, 4);
        $data = substr($payload, 14);
    } else {
        $masks = substr($payload, 2, 4);
        $data = substr($payload, 6);
    }
    
    $text = '';
    for ($i = 0; $i < strlen($data); $i++) {
        $text .= $data[$i] ^ $masks[$i % 4];
    }
    
    return $text;
}

function mask($text) {
    $b1 = 0x80 | (0x1 & 0x0f);
    $length = strlen($text);
    
    if ($length <= 125) {
        $header = pack('CC', $b1, $length);
    } elseif ($length > 125 && $length < 65536) {
        $header = pack('CCn', $b1, 126, $length);
    } else {
        $header = pack('CCNN', $b1, 127, $length);
    }
    
    return $header . $text;
}

function send($client, $message) {
    socket_write($client, mask(json_encode($message)));
}

function broadcast($clients, $message, $exclude = null) {
    foreach ($clients as $client) {
        if ($client !== $exclude) {
            send($client, $message);
        }
    }
}

function handleMessage($data, $client, &$clients, &$meetings) {
    $type = $data['type'] ?? '';
    
    switch ($type) {
        case 'join':
            $meetingId = $data['meetingId'];
            $userId = $data['userId'];
            $userName = $data['userName'];
            
            if (!isset($meetings[$meetingId])) {
                $meetings[$meetingId] = [];
            }
            
            $meetings[$meetingId][$userId] = [
                'socket' => $client,
                'name' => $userName
            ];
            
            broadcast($clients, [
                'type' => 'user-joined',
                'userId' => $userId,
                'userName' => $userName
            ], $client);
            break;
            
        case 'leave':
            foreach ($meetings as $meetingId => &$participants) {
                foreach ($participants as $userId => $participant) {
                    if ($participant['socket'] === $client) {
                        broadcast($clients, [
                            'type' => 'user-left',
                            'userId' => $userId,
                            'userName' => $participant['name']
                        ]);
                        
                        unset($participants[$userId]);
                        break 2;
                    }
                }
            }
            break;
            
        case 'offer':
        case 'answer':
        case 'ice-candidate':
            $targetId = $data['targetId'];
            
            foreach ($meetings as $participants) {
                if (isset($participants[$targetId])) {
                    $targetSocket = $participants[$targetId]['socket'];
                    
                    $message = $data;
                    $message['fromId'] = array_search(['socket' => $client], $participants);
                    
                    send($targetSocket, $message);
                    break;
                }
            }
            break;
            
        case 'chat-message':
            broadcast($clients, $data, $client);
            break;
    }
}