<?php

require_once __DIR__ . '/php/locations/locations.php';

global $config;

$config = new stdClass();
$userFile = null;

// Do we know you? Look for id in HTTP header...
if (isset($_SERVER['HTTP_X_AUTOPILOT_USERID'])) {
    $userId = $_SERVER['HTTP_X_AUTOPILOT_USERID'];
    $userFile = get_user_config_file_name($userId);
    if (file_exists($userFile)) {
        if (file_exists('/opt/autopilot/users/blocked/' . $userId)) {
            // Only time we admit that there's something here is for a blocked user, this will cause the web app to clear any storage and unregister service worker
            do_403();
        }
        $config->user['UserId'] = $userId;
        $fileHandle = file($userFile, FILE_IGNORE_NEW_LINES);
        foreach ($fileHandle as $value) :
            $row = str_getcsv($value);
            if ($row[0] === 'FavLoc' || $row[0] === 'FavJny') {
                $config->user[$row[0]][] = (count($row) - 1) > 1 ? array_slice($row, 1) : $row[1];  // Only use an array where more than one item
            } else {
                $config->user[$row[0]] = $row[1];  // Simple name-value pair
            }
        endforeach;
        $config->lastModified = gmdate('D, d M Y H:i:s T', filemtime($userFile));
    } else {
        do_404();
    }
} else {
    do_404();
}

// Now get global config if any
$configFile = get_global_config_file_name();
if (file_exists($configFile)) {
    $fileHandle = file($configFile, FILE_IGNORE_NEW_LINES);
    foreach ($fileHandle as $key => $value) :
        $row = str_getcsv($value);
        $config->app[$row[0]][] = (count($row) - 1) > 1 ? array_slice($row, 1) : $row[1];  // Only use an array where more than one item
    endforeach;
    if (filemtime($configFile) > filemtime($userFile)) {
        $config->lastModified = gmdate('D, d M Y H:i:s T', filemtime($configFile));
    }
} else {
    $config = array();
}

// FIXME Throws an exception
// if (array_key_exists('MaintenanceMode', $config) && !is_god_mode()) {
//     do_503();
// }

function do_403()
{
    http_response_code(403);
    if (isset($_COOKIE['sessionId'])) {
        unset($_COOKIE['sessionId']);
        setcookie('sessionId', '', [   // empty value and old timestamp (1 hour ago) so that it expires immediately
            'expires' => time() - 3600,
            'path' => '/',
            'domain' => NULL,
            'secure' => true,
            'httponly' => false,
            'samesite' => 'Strict',
        ]);
    }
    die();
}

function do_404($message = null)
{
    if (isset($message)) {
        echo $message;
    }
    http_response_code(404);
    if (isset($_COOKIE['sessionId'])) {
        unset($_COOKIE['sessionId']);
        setcookie('sessionId', '', [   // empty value and old timestamp (1 hour ago) so that it expires immediately
            'expires' => time() - 3600,
            'path' => '/',
            'domain' => NULL,
            'secure' => true,
            'httponly' => false,
            'samesite' => 'Strict',
        ]);
    }
    die();
}

function do_503()
{
    http_response_code(503);
    die();
}

function is_location_favourite(string $reqLoc)
{
    global $config;

    $found = false;
    if (isset($config->user['FavLoc'])) {
        foreach ($config->user['FavLoc'] as $loc) {
            if ($loc === $reqLoc) {
                $found = true;
                break;
            }
        }
    }

    return $found;
}

function is_journey_favourite(string $reqLoc, string $reqFilter)
{
    global $config;

    $found = false;
    if (isset($config->user['FavJny'])) {
        foreach ($config->user['FavJny'] as $jny) {
            if ($jny[0] === $reqLoc && $jny[1] === $reqFilter) {
                $found = true;
                break;
            }
        }
    }

    return $found;
}

function add_favourite(string $loc, string $filterLoc = '')
{
    global $config;

    if ($filterLoc === '') {
        if (!is_location_favourite($loc)) {
            $config->user['FavLoc'][] = $loc;
        }
    } else {
        if (!is_journey_favourite($loc, $filterLoc)) {
            $config->user['FavJny'][] = [$loc, $filterLoc];
        }
    }

    save_user_config();
}

function remove_favourite(string $loc, string $filterLoc = '')
{
    global $config;

    if ($filterLoc === '') {
        $config->user['FavLoc'] = array_diff($config->user['FavLoc'], array($loc));
    } else {
        $key = array_search(array($loc, $filterLoc), $config->user['FavJny']);
        if ($key !== false) {
            unset($config->user['FavJny'][$key]);
        }
    }

    save_user_config();
}

function favourite_locations($realm = '')
{
    global $config;

    $sorted_locations = array_filter($config->user['FavLoc'], function ($candidate) use ($realm) {
        return $realm === '' || strpos($candidate, $realm) === 0;
    }) ?? [];
    sort($sorted_locations);

    return $sorted_locations;
}

function favourite_journeys($realm = '')
{
    global $config;

    $sorted_journeys = array_filter($config->user['FavJny'], function ($candidate) use ($realm) {
        return $realm === '' || strpos($candidate[0], $realm) === 0;
    }) ?? [];
    sort($sorted_journeys);

    return $sorted_journeys;
}

function save_user_config()
{
    global $config;

    $fileHandle = fopen(get_user_config_file_name(), 'w');

    if ($fileHandle !== false) {
        foreach ($config->user as $itemType => $itemData) {
            if ($itemType === 'Name' || $itemType === 'Email' || $itemType === 'Mobile' || $itemType === 'SearchOpt' || $itemType === 'GodMode') { // One item
                fwrite($fileHandle, $itemType . ',' . $itemData[0] . PHP_EOL);
            } else if ($itemType === 'FavLoc') { // array
                foreach ($itemData as $favLoc) {
                    fwrite($fileHandle, $itemType . ',' . $favLoc . PHP_EOL);
                }
            } else if ($itemType === 'FavJny') { // 2-D array
                foreach ($itemData as $favJny) {
                    fwrite($fileHandle, $itemType . ',' . $favJny[0] . ',' . $favJny[1] . PHP_EOL);
                }
            }
        }

        fclose($fileHandle);
    }
}

function is_god_mode()
{
    global $config;

    return array_key_exists('GodMode', $config->user);
}

function get_user_config_file_name($userId = null)
{
    global $config;

    return '/opt/autopilot/users/' . ($userId ?? $config->user['UserId']) . '.csv';
}

function get_global_config_file_name()
{
    return '/opt/autopilot/config.csv';
}

function getConfiguration()
{
    global $config;

    $returnedConfig = clone $config;

    // Remove unnecessary PII from the config
    unset($returnedConfig->user['Email']);
    unset($returnedConfig->user['Mobile']);

    // Set names
    if (isset($returnedConfig->user['FavLoc'])) {
        foreach ($returnedConfig->user['FavLoc'] as &$favLoc) {
            // Turn single item into array of id and full name
            $favLoc = array($favLoc);
            $favLoc[] = Locations::GetLocationName($favLoc[0]);
        }
    }

    if (isset($returnedConfig->user['FavJny'])) {
        foreach ($returnedConfig->user['FavJny'] as &$favJny) {
            // Turn O and D ends into array of id and full name
            $favJny[0] = array($favJny[0]);
            $favJny[0][] = Locations::GetLocationName($favJny[0][0]);
            $favJny[1] = array($favJny[1]);
            $favJny[1][] = Locations::GetLocationName($favJny[1][0]);
        }
    }

    return $returnedConfig;
}
