<?php

declare(strict_types=1);

const IP_FILE = __DIR__ . '/ip.txt';
const BACKEND_PORT = 2568;
const BACKEND_AUTH = 'b3BlcmF0b3JlOnB0UVUyN2JMTDk5d2Uh';

function fail(int $status, string $message): never
{
    http_response_code($status);
    header('Content-Type: text/plain; charset=utf-8');
    echo $message . "\n";
    exit;
}

if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'GET') {
    header('Allow: GET');
    fail(405, 'method not allowed');
}

$path =  'frame.jpg?id='.time();



$ip = trim((string) @file_get_contents(IP_FILE));
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
    fail(503, 'webcam IP is unavailable');
}

$url = 'http://' . $ip . ':' . BACKEND_PORT . '/' . $path;
if ($query !== []) {
    $url .= '?' . http_build_query($query, '', '&', PHP_QUERY_RFC3986);
}

$headersApplied = false;
$responseStatus = 502;
$responseHeaders = [];
$curl = curl_init($url);
if ($curl === false) {
    fail(500, 'cannot initialize backend request');
}

curl_setopt_array($curl, [
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_MAXREDIRS => 3,
    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_TIMEOUT => 20,
    CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
    CURLOPT_USERPWD => base64_decode(BACKEND_AUTH, true),
    CURLOPT_HEADERFUNCTION => static function ($handle, string $header) use (&$responseStatus, &$responseHeaders): int {
        $line = trim($header);
        if ($line === '') {
            return strlen($header);
        }
        if (preg_match('#^HTTP/#i', $line)) {
            $responseStatus = (int) preg_replace('#^HTTP/\\S+\\s+(\\d{3}).*$#', '$1', $line);
            $responseHeaders = [];
            return strlen($header);
        }
        [$name, $value] = array_pad(explode(':', $line, 2), 2, '');
        $name = trim($name);
        $value = trim($value);
        if (in_array(strtolower($name), ['content-type', 'cache-control', 'last-modified'], true)) {
            $responseHeaders[$name] = $value;
        }
        return strlen($header);
    },
    CURLOPT_WRITEFUNCTION => static function ($handle, string $chunk) use (&$headersApplied, &$responseStatus, &$responseHeaders): int {
        if (!$headersApplied) {
            http_response_code($responseStatus);
            foreach ($responseHeaders as $name => $value) {
                header($name . ': ' . $value, true);
            }
            $headersApplied = true;
        }
        echo $chunk;
        return strlen($chunk);
    },
]);

$ok = curl_exec($curl);
if ($ok === false && !$headersApplied) {
    $error = curl_error($curl);
    curl_close($curl);
    fail(502, 'backend request failed: ' . $error);
}
if (!$headersApplied) {
    http_response_code((int) curl_getinfo($curl, CURLINFO_RESPONSE_CODE));
    foreach ($responseHeaders as $name => $value) {
        header($name . ': ' . $value, true);
    }
}
curl_close($curl);
