<?php
define('FTM_ROOT', __DIR__ . '/..');
define('FTM_PATH_PUB', FTM_ROOT . '/public');
define('FTM_PATH_PRV', FTM_ROOT . '/private');

define('FTM_LEGACY_SOUND_TYPE', [
    'opus' => 'audio/ogg',
    'ogg' => 'audio/ogg',
    'mp3' => 'audio/mpeg',
    'caf' => 'audio/x-caf',
    'wav' => 'audio/wav',
]);

header('X-Powered-By: Futami');
header('Cache-Control: max-age=86400, must-revalidate');
header('Access-Control-Allow-Origin: *');

$reqMethod = (string)filter_input(INPUT_SERVER, 'REQUEST_METHOD');
if($reqMethod === 'OPTIONS') {
    http_response_code(204);
    header('Access-Control-Allow-Methods: OPTIONS, GET');
    header('Access-Control-Allow-Headers: Cache-Control');
    return;
}

if($reqMethod !== 'HEAD' && $reqMethod !== 'GET') {
    http_response_code(405);
    return;
}

function json_out($data): void {
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($data);
    exit;
}

function match_etag($eTag): void {
    if(filter_input(INPUT_SERVER, 'HTTP_IF_NONE_MATCH') === $eTag) {
        http_response_code(304);
        exit;
    }
}
function gen_etag(string $user, string $data): string {
    return sprintf('W/"%s-%s"', hash('sha1', $data), $user);
}
function gen_etag_file(string $user, string $path): string {
    return gen_etag($user, hash_file('sha1', $path));
}
function etag(string $etag): void {
    match_etag($etag);
    header('ETag: ' . $etag);
}
function etag_data(string $user, string $data): void {
    etag(gen_etag($user, $data));
}
function etag_file(string $user, string $path): void {
    etag(gen_etag_file($user, $path));
}

$reqPath = '/' . trim(parse_url((string)filter_input(INPUT_SERVER, 'REQUEST_URI'), PHP_URL_PATH), '/');

if($reqPath === '/common.json') {
    $commonPath = FTM_PATH_PRV . '/common.ini';
    etag_file('common', $commonPath);

    $common = parse_ini_file($commonPath, false, INI_SCANNER_TYPED);

    $colours = $common['colours'];
    $common['colours'] = [];
    foreach($colours as $n => $c)
        $common['colours'][] = compact('n', 'c');

    json_out($common);
}

if($reqPath === '/sounds.json') {
    $sndLibData = file_get_contents(FTM_PATH_PRV . '/sound-library.ini');
    $sndPackData = file_get_contents(FTM_PATH_PRV . '/sound-packs.ini');

    etag_data('sounds', $sndLibData . $sndPackData);

    $sndLib = parse_ini_string($sndLibData, true, INI_SCANNER_TYPED);
    $sndPacks = parse_ini_string($sndPackData, true, INI_SCANNER_TYPED);

    $library = [];
    foreach($sndLib as $name => $info) {
        $sources = [];
        foreach($info['sources'] as $type => $path) {
            $sources[] = [
                'format' => FTM_LEGACY_SOUND_TYPE[$type],
                'url' => $path,
            ];
        }

        $library[] = [
            'id' => $name,
            'name' => $info['title'],
            'sources' => $sources,
        ];
    }

    $packs = [];
    foreach($sndPacks as $name => $info) {
        $packs[] = [
            'id' => $name,
            'name' => $info['title'],
            'events' => $info['events'],
        ];
    }

    json_out(compact('library', 'packs'));
}

if($reqPath === '/soundtriggers.json') {
    $textTriggersPath = FTM_PATH_PRV . '/text-triggers.ini';
    etag_file('soundtriggers', $textTriggersPath);

    $textTriggers = parse_ini_file($textTriggersPath, true, INI_SCANNER_TYPED);
    $sndLib = parse_ini_file(FTM_PATH_PRV . '/sound-library.ini', true, INI_SCANNER_TYPED);
    $soundTrigs = [];

    foreach($textTriggers as $triggerInfo) {
        if($triggerInfo['type'] !== 'sound' && $triggerInfo['type'] !== 'alias')
            continue;

        $soundTrig = [];

        if($triggerInfo['type'] === 'sound') {
            $sounds = [];

            foreach($triggerInfo['sounds'] as $soundName) {
                if(!isset($sndLib[$soundName]))
                    continue;

                $sound = [];
                $libSound = $sndLib[$soundName];

                if(isset($libSound['sources']['mp3']))
                    $sound['m'] = $libSound['sources']['mp3'];
                if(isset($libSound['sources']['ogg']))
                    $sound['o'] = $libSound['sources']['ogg'];
                if(isset($libSound['sources']['opus']))
                    $sound['o'] = $libSound['sources']['opus'];
                if(isset($libSound['sources']['caf']))
                    $sound['c'] = $libSound['sources']['caf'];

                if(empty($sound))
                    continue;

                if(isset($triggerInfo['volume'])) {
                    $sound['v'] = ceil(($triggerInfo['volume'] - 1) * 100);
                    $sound['v2'] = $triggerInfo['volume'];
                }

                if(isset($triggerInfo['rate']))
                    $sound['r'] = $triggerInfo['rate'];

                $sounds[] = $sound;
            }

            $soundTrig['s'] = $sounds;
        } elseif($triggerInfo['type'] === 'alias') {
            $soundTrig['f'] = $triggerInfo['for'];
        }

        $matches = [];
        foreach($triggerInfo['match'] as $match) {
            $filters = [];
            $value = null;
            $notValue = null;

            $parts = explode(';', $match);
            foreach($parts as $part) {
                $part = explode(':', trim($part));

                switch($part[0]) {
                    case 'lc':
                        $filters[] = 'lower';
                        break;
                    case 'is':
                        $filters[] = 'exact';
                        $value = trim($part[1]);
                        break;
                    case 'starts':
                        $filters[] = 'starts';
                        $value = trim($part[1]);
                        break;
                    case 'has':
                        $filters[] = 'contains';
                        $value = trim($part[1]);
                        break;
                    case 'hasnot':
                        $notValue = trim($part[1]);
                        break;
                    default:
                        $filters[] = 'missing:' . $part[0];
                        break;
                }
            }

            $matchNew = ['t' => implode(':', $filters)];
            if($value !== null)
                $matchNew['m'] = $value;
            if($notValue !== null)
                $matchNew['n'] = $notValue;

            $matches[] = $matchNew;
        }
        $soundTrig['t'] = $matches;

        $soundTrigs[] = $soundTrig;
    }

    json_out([
        'meta' => [
            'baseUrl' => '',
        ],
        'triggers' => $soundTrigs,
    ]);
}

if($reqPath === '/' || $reqPath === '/index.html' || $reqPath === '/index.php') {
    header('Content-Type: text/html; charset=utf-8');
    echo <<<HTML
    <!doctype html>
    Data and settings shared between both chat clients is stored on this subdomain.
    HTML;
    return;
}

http_response_code(404);