<?php error_reporting(E_ALL);

/**
 * For demo purposes only
 *
 * php -S localhost:8000
 * http://localhost:8000
 */

use Many\Http\Curler;
use Many\Http\Response;
use Many\Exception\AppCallbackException;

require_once dirname(__DIR__) . '/vendor/autoload.php';
require_once __DIR__ . '/callback.functions.php';

/** Get file content in a browser */
if ('self' === ($_GET['check'] ?? null))
{
    exit(highlight_file(__FILE__, true));
}

/** @var string (optional) default URL */
$defaultUrl = 'https://upload.wikimedia.org/wikipedia/commons/thumb';

/** @var array Images to test "img to string" converter, will use $defaultUrl */
$imgList = [
    '/8/80/Andaman.jpg/250px-Andaman.jpg',
    '/2/21/Aurora_and_sunset.jpg/250px-Aurora_and_sunset.jpg',
];

/** @var string File with json content */
$jsonFile = 'https://raw.githubusercontent.com/eypsilon/Curler/master/www.example.json';

/** @var array some URLs to load */
$loadUrls = [
    'http://example.com/',
    'https://raw.githubusercontent.com/eypsilon/browser-reload/master/LICENSE',
    'https://github.com/eypsilon/MycroBench',
];

/** @var string default Url for Live tester */
$defaultLiveUrl = 'https://mycro-bench.vercel.app/?x-times=5';

/**
 * @var array Set Config
 */
Curler::setConfig([
    'enable_history'    => true,  // Für getHistory() / getCurlTrace()
    'enable_exceptions' => true,  // Für Exceptions
    'enable_meta'       => true,  // Für Meta-Informationen
    'default_url'       => null,
    'date_format'       => 'Y-m-d H:i:s.u',
    'image_to_data'     => ['image/jpeg'],
    'default_headers'   => [
        'x-app-curler' => 'Many/Curler',
        'Content-Type' => 'application/json',
    ],
    'default_options'   => [
        CURLOPT_USERAGENT => 'AwesomeUser',
        CURLOPT_ENCODING   => 'gzip, deflate',  
    ],
    'retry_attempts'    => 0,
    'retry_delay_ms'    => 100,
    'retry_on_status'   => [429, 500, 502, 503, 504],
]);

/**
 * @var Curler extended example with multiple callbacks (order matters)
 */
try {
    $curled['curler_info'] = '<b>Loads the content of a JSON file and executes some callback functions in a row</b> <small>(7 to be specific)</small>';
    
    $response = (new Curler)
        // ->disableDefaultUrl()
        // ->responseOnly()
        
        // callbacks, see "./callback.functions.php"
        ->through(fn($r) => curlCallback($r))
        ->through(fn($r) => curlCallbackTwo($r))
        ->through(fn($r) => curlCallbackThree($r))

        // using a class
        ->through(fn($r) => CallbackClass::run($r))
        ->through(fn($r) => (new CallbackClass())->init($r))

        // using a closure
        ->through(function($response) {
            return curlConv($response, 'closure_callback');
        })

        // pre validate content 
        ->validate(fn($r) => is_string($r), 'Must be string')
        ->jsonDecode()
        ->jsonEncode()
        ->through(fn($r) => curlConv($r, 'done_too'))
        ->jsonDecode()
        ->jsonEncode(JSON_PRETTY_PRINT)
        ->through(fn($r) => htmlspecialchars($r))
        ->get($jsonFile);
        
    $curled['curler'] = [
        'url'          => $response->getMeta('url') ?? $jsonFile,  // <- Fallback
        'http_code'    => $response->getStatusCode(),
        'status'       => $response->isSuccess() ? 'ok' : 'error',
        'method'       => $response->getMeta('method') ?? 'GET',  // <- Fallback
        'content_type' => $response->getContentType(),
        'meta'         => $response->getMeta(),
        'error'        => $response->isSuccess() ? null : "HTTP {$response->getStatusCode()}",
        'response'     => $response->getBody(),
    ];
} catch(AppCallbackException $e) {
    $curled['exception']['curler'] = $e->getMessage();
} catch(RuntimeException $e) {
    $curled['exception']['curler'] = $e->getMessage();
}

/**
 * @var array Load multiple URLs
 */
$curled['load_urls_info'] = '<b>Loads a handful of URLs and truncates the response</b>';
foreach($loadUrls as $i => $url) {
    try {
        $response = (new Curler)
            ->through(fn($r) => htmlspecialchars($r))
            ->through('trim')
            ->through(fn($r) => substr($r, 0, 20))
            ->through(fn($r) => appendString($r, '… ' . Curler::dateMicroSeconds()))
            ->get($url);
            
        $curled['load_urls'][] = [
            'url' => $url,
            'status' => $response->getStatusCode(),
            'response' => $response->getBody(),
        ];
    } catch(AppCallbackException $e) {
        $host = parse_url((string) $url, PHP_URL_HOST);
        $curled['exception']['load_urls'][$host] = $e->getMessage();
    } catch(RuntimeException $e) {
        $host = parse_url((string) $url, PHP_URL_HOST);
        $curled['exception']['load_urls'][$host] = $e->getMessage();
    }
}

/**
 * @var Curler Load images, change configs to get datetime for images, set default URL and image converter
 */
Curler::setConfig([
    'enable_meta' => true,
    'enable_history' => true,  
    'default_url' => $defaultUrl,
    'image_to_data' => ['image/jpeg', /* 'image/png', */],
]);

$c = new Curler;
$printImages = [];
$curled['loaded_images_info'] = '<b>The images displayed above, the responses are truncated</b>';

foreach($imgList as $img) {
    try {
        $response = $c->get($img);
        
        if ($response->isSuccess()) {
            $body = $response->getBody();
            $printImages[] = sprintf('<img src="%s" alt="%s" style="height:130px" />', $body, $img);
            $curled['loaded_images'][] = [
                'response' => substr($body, 0, 35) . ' …',
                'http_code' => $response->getStatusCode(),
                'type' => $response->getContentType(),
                'meta' => $response->getMeta(),
            ];
        }
    } catch(AppCallbackException $e) {
        $curled['exception']['images'][$img] = $e->getMessage();
    } catch(RuntimeException $e) {
        $curled['exception']['images'][$img] = $e->getMessage();
    }
}

$url = $_GET['url'] ?? null;
$setUrl = is_string($url) ? $url : $defaultLiveUrl;
$linkelf = $_SERVER['PHP_SELF'] ?? './index.php';

/**
 * @Template\Engin © 1994 eypsilon
 */
?><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title><?= $cName = 'Many\Curler' ?> | local-dev-many-title</title>
<meta name="description" content="<?= $cName ?> Example Page" />
<style>
header, footer {text-align: center;}
header h1 {margin: 0;}
header p {margin: 5px 0;}
fieldset {margin: 10px 0; padding: 5px; display: flex; background: #f5f5f5; border-color: #fff;}
input {width: 100%; border-width: 1px 0;}
[type=button] {pointer-events: none; color: #999;}
input, button {display: block; padding: 6px 10px;}
pre {margin: 1.5em 0; white-space: pre-wrap;}
hr {margin: 1em 0;}
h2 small {margin: 5px 0 0; display: block; font-size: .8rem;}
</style>
</head>
<body>
<header>
    <h1><a href="<?= $linkelf ?>"><?= $cName ?></a></h1>
    <p>another one curls the dust</p>
</header>
<form action="" method="get">
    <fieldset>
        <button type="button">test</button>
        <input type="text" name="url" value="<?= htmlspecialchars($setUrl) ?>" placeholder="Enter a URL" />
        <button type="submit">Get</button>
    </fieldset>
</form>
<?php

// live curler
if (is_string($url) AND false === filter_var($url, FILTER_VALIDATE_URL)) {
    printf('<h2>%s\Live</h2><pre>FILTER_VALIDATE_URL_FAILED <b>%s</b></pre><hr />'
        , $cName
        , htmlspecialchars($url)
    );
} elseif (is_string($url) AND is_string(filter_var($url, FILTER_VALIDATE_URL))) {
    try {
        $response = (new Curler)
            ->disableDefaultUrl()
            ->through(fn($r) => htmlspecialchars($r))
            ->get($url);
            
        printf('<h2>%1$s\Live <small><a href="%2$s">%2$s</a></small></h2><pre>%3$s</pre><hr />'
            , $cName
            , htmlspecialchars($url)
            , $response->getBody()
        );
    } catch(Exception $e) {
        printf('<h2>%s\Live Error</h2><pre>%s</pre><hr />'
            , $cName
            , htmlspecialchars($e->getMessage())
        );
    }
}

// out
printf('%s<h2>Some requests</h2><pre>%s</pre>'
    , implode(PHP_EOL, $printImages)
    , print_r(array_merge($curled, [
        'getCurlCount' => Curler::getRequestCount(),
        'getCurlTrace' => array_map(
            function($entry) {
                if (is_array($entry)) {
                    return sprintf(
                        '[%s] %s %s (%s)',
                        $entry['method'] ?? 'GET',
                        $entry['status'] ?? '???',
                        $entry['url'] ?? 'unknown',
                        $entry['duration'] ?? '0'
                    );
                }
                return $entry;
            }, Curler::getHistory()
        ),
        'getConfig'  => Curler::getConfig(),
        'getOptions' => Curler::getOptions(),
    ]), true)
);

// responder/receiver example
printf('<hr /><h3>Responder/Receiver Example</h3> %s <hr />
    <p><a href="?check=self">Check current file</a></p>'
    , highlight_file(__DIR__ . '/app.responder.receiver.php', true)
);

// advanced benchmarks
printf("<hr /><pre>start: %s\nend:   %s\ndiff:  %s\nmem:   %s\npeak:  %s</pre>"
    , $started = Curler::dateMicroSeconds($_SERVER['REQUEST_TIME_FLOAT'] ?? null, 'H:i:s.u')
    , $current = Curler::dateMicroSeconds(null, 'H:i:s.u')
    , Curler::dateMicroDiff($started, $current, '%s.%f')
    , Curler::formatBytes(memory_get_usage())
    , Curler::formatBytes(memory_get_peak_usage())
);
?>
<hr />
<footer>
    <p>© <?= date('Y') ?> <?= $cName ?> | <a href="https://github.com/eypsilon/Curler">github</a></p>
</footer>
</body>
</html>