<?php
set_time_limit(0);

$host = "0.0.0.0";
$port = 8080;

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, $host, $port);
socket_listen($socket);

$clients = [];
$users = loadData();
$rooms = initRooms();

echo "Server running...\n";

while (true) {
    $read = $clients;
    $read[] = $socket;

    socket_select($read, $write = NULL, $except = NULL, 0, 10);

    if (in_array($socket, $read)) {
        $new = socket_accept($socket);
        $clients[] = $new;
        handshake($new);
        echo "New connection\n";
    }

    foreach ($clients as $client) {
        $data = @socket_read($client, 2048, PHP_BINARY_READ);

        if ($data === false) continue;

        $msg = unmask($data);
        if (!$msg) continue;

        $json = json_decode($msg, true);
        handleMessage($client, $json);
    }
}

function loadData() {
    if (!file_exists("data.json")) return [];
    return json_decode(file_get_contents("data.json"), true);
}

function saveData($data) {
    file_put_contents("data.json", json_encode($data, JSON_PRETTY_PRINT));
}

function initRooms() {
    $rooms = [];
    for ($i = 1; $i <= 5; $i++) {
        $rooms[$i] = [
            "players" => [],
            "deck" => [],
            "dealer" => []
        ];
    }
    return $rooms;
}

function createUser(&$users, $name) {
    if (!isset($users[$name])) {
        $users[$name] = [
            "money" => 500,
            "bonus" => 100,
            "lastBonus" => time()
        ];
    }

    // weekly bonus
    if (time() - $users[$name]["lastBonus"] > 604800) {
        $users[$name]["bonus"] = min(200, $users[$name]["bonus"] + 100);
        $users[$name]["lastBonus"] = time();
    }

    return $users[$name];
}

function newDeck() {
    $deck = [];
    foreach (["H","D","C","S"] as $s) {
        foreach ([2,3,4,5,6,7,8,9,10,"J","Q","K","A"] as $v) {
            $deck[] = $v.$s;
        }
    }
    shuffle($deck);
    return $deck;
}

function cardValue($card) {
    $v = substr($card, 0, -1);
    if (in_array($v, ["J","Q","K"])) return 10;
    if ($v == "A") return 11;
    return (int)$v;
}

function score($hand) {
    $total = 0;
    foreach ($hand as $c) $total += cardValue($c);
    return $total;
}

function handleMessage($client, $msg) {
    global $users, $rooms;

    switch ($msg["type"]) {

        case "login":
            $user = createUser($users, $msg["name"]);
            saveData($users);
            send($client, ["type"=>"user","data"=>$user]);
        break;

        case "join":
            $room = $msg["room"];
            $rooms[$room]["players"][] = [
                "client"=>$client,
                "name"=>$msg["name"],
                "hand"=>[],
                "bet"=>0
            ];
        break;

        case "bet":
            $room = $msg["room"];
            foreach ($rooms[$room]["players"] as &$p) {
                if ($p["name"] == $msg["name"]) {
                    $p["bet"] = $msg["amount"];
                    $users[$msg["name"]]["money"] -= $msg["amount"];
                }
            }
            saveData($users);
        break;

        case "start":
            $room = $msg["room"];
            $rooms[$room]["deck"] = newDeck();

            foreach ($rooms[$room]["players"] as &$p) {
                $p["hand"] = [
                    array_pop($rooms[$room]["deck"]),
                    array_pop($rooms[$room]["deck"])
                ];
            }

            $rooms[$room]["dealer"] = [
                array_pop($rooms[$room]["deck"]),
                array_pop($rooms[$room]["deck"])
            ];

        break;

        case "hit":
            $room = $msg["room"];
            foreach ($rooms[$room]["players"] as &$p) {
                if ($p["name"] == $msg["name"]) {
                    $p["hand"][] = array_pop($rooms[$room]["deck"]);
                }
            }
        break;

        case "stand":
            // dealer logic
        break;
    }
}

function send($client, $data) {
    $msg = mask(json_encode($data));
    @socket_write($client, $msg, strlen($msg));
}

/* websocket helpers (minimal) */
function handshake($client) {
    $request = socket_read($client, 5000);
    preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $request, $match);
    $key = base64_encode(pack('H*', sha1($match[1].'258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
    $headers = "HTTP/1.1 101 Switching Protocols\r\n".
               "Upgrade: websocket\r\n".
               "Connection: Upgrade\r\n".
               "Sec-WebSocket-Accept: $key\r\n\r\n";
    socket_write($client, $headers, strlen($headers));
}

function mask($text) {
    $b1 = 0x81;
    $length = strlen($text);
    return chr($b1).chr($length).$text;
}

function unmask($payload) {
    $length = ord($payload[1]) & 127;
    $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;
}