<?php

#ini_set("display_errors", "on");
use QUI\Setup\Output\Interfaces\Output;
use QUI\Setup\Setup;

if (!isset($_GET['step'])) {
    $_GET['step'] = '';
}

$Composer = require_once dirname(__FILE__) . '/vendor/autoload.php';
$Composer->loadClass('Composer\Console\GithubActionError'); // workaround for 7.3/7.4
$Composer->loadClass('React\Promise\RejectedPromise'); // workaround for 7.3/7.4


// Load QUIQQER, if QUIQQER has been installed already.
if ($_GET['step'] === "installpreset" || $_GET['step'] === "installpreset2" || $_GET['step'] === "setuppreset" || $_GET['step'] === 'lastsetup') {
    # Apply preset
    if (!defined('QUIQQER_SYSTEM')) {
        define('QUIQQER_SYSTEM', true);
    }

    //Workaround
    define('QUIQQER_SETUP', true);

    require_once dirname(__FILE__) . "/bootstrap.php";
    ini_set("display_errors", 0);
}
?>
    <html>
    <head>
        <style>
            body {
                background: #000;
                color: #fff;
                padding: 20px;
            }

            pre {
                margin: 0;
                padding: 0;
            }
        </style>
    </head>


<?php

// Output the previous steps log messages if they exists.
if (file_exists(dirname(__FILE__) . "/var/weboutput.log")) {
    $previousMessages = file_get_contents(dirname(__FILE__) . "/var/weboutput.log");
    echo $previousMessages;
}

// Configure the proper output
error_reporting(E_ERROR | E_WARNING);
ini_set('display_errors', 0);
ini_set("error_log", dirname(__FILE__) . "/var/log/setup.log");
ob_start();

// Load stored setup data
$dataFile = dirname(__FILE__) . "/setupdata.json";
if (!file_exists($dataFile)) {
    echo "Missing setupdata.json";
    \QUI\Setup\Log\Log::error("Missing setupdata.json");
    exit;
}
$data = json_decode(file_get_contents($dataFile), true);

$neededClasses = [
    'QUI\Setup\Setup',
    'QUI\Setup\Preset',
    'QUI\Setup\SetupException',
    'QUI\Setup\Locale\LocaleInterface',
    'QUI\Setup\Locale\Locale',
    'QUI\Setup\Locale\IniLocale',
    'QUI\Setup\Locale\LocaleException',
    'QUI\Setup\Output\Interfaces\Output',
    'QUI\Setup\Output\WebOutput',
    'QUI\Setup\Log\Log',
    'QUI\Setup\Utils\Ajax',
    'QUI\Setup\Utils\Utils',
    'QUI\Setup\Utils\Validator',
];

foreach ($neededClasses as $class) {
    if (!class_exists($class)) {
        require_once dirname(__FILE__) . '/src/' . str_replace('\\', '/', $class) . '.php';
    }
}

// Initiliaze the setup
$Setup = new QUI\Setup\Setup(QUI\Setup\Setup::MODE_WEB);

$language = $_REQUEST['language'] ?? "en";
try {
    $Setup->setSetupLanguage($language);
} catch (\Exception $Exception) {
}

##############################################################################
# Setup
##############################################################################

# Execute the setup and redirect to preset installation after finish
if (empty($_GET['step'])) {
    prepareSetup();
}

if ($_GET['step'] === 'installquiqqer') {
    installQUIQQER();
}

if ($_GET['step'] === 'setupquiqqer') {
    setupQUIQQER();
}

if ($_GET['step'] === 'installpreset') {
    QUI\Setup\Log\Log::append("Install preset start - " . date("H:i:s"));
    installPreset();
    QUI\Setup\Log\Log::append("Install preset end - " . date("H:i:s"));
}

if ($_GET['step'] === 'installpreset2') {
    QUI\Setup\Log\Log::append("Install preset start - " . date("H:i:s"));
    installPreset(2);
    QUI\Setup\Log\Log::append("Install preset end - " . date("H:i:s"));
}

if ($_GET['step'] === 'setuppreset') {
    QUI\Setup\Log\Log::append("Setup preset start - " . date("H:i:s"));
    setupPreset();
    QUI\Setup\Log\Log::append("Setup preset end - " . date("H:i:s"));
}

if ($_GET['step'] === 'lastsetup') {
    QUI\Setup\Log\Log::append("Last Setup start - " . date("H:i:s"));

    // last complete setup
    $Setup->Output->writeLnLang("Project setup start", Output::LEVEL_INFO);

    $User = QUI::getUsers()->getUsers([
        'where' => [
            'su' => 1
        ],
        'limit' => 1
    ])[0];

    QUI\Permissions\Permission::setUser($User);

    QUI::$PackageManager = null;

    QUI\Cache\Manager::clear('qui/projects');
    QUI\Cache\Manager::clear('quiqqer/projects');

    QUI\Cache\Manager::clearAll();
    QUI\Cache\LongTermCache::clear();

    $Projects = QUI::getProjectManager();
    $projects = $Projects->getProjects(true);

    foreach ($projects as $Project) {
        $cachePath = $Project->getCachePath();

        QUI\Cache\Manager::clear($cachePath . '/configList');
        QUI\Cache\Manager::clear($cachePath . '/relatedSettingsXml');

        $Project->setup();
    }

    // do last update
    $Setup->Output->writeLnLang("Filesystem cleanup", Output::LEVEL_INFO);
    \QUI\Setup\Log\Log::append("Cleanup");
    $Setup->deleteSetupFiles();

    \QUI\Setup\Log\Log::append("Done with setting up the preset");
    \QUI\Setup\Log\Log::append("Done with the last update");

    QUI\Setup\Log\Log::append("Last Setup end - " . date("H:i:s"));
    $Setup->Output->executeParentJSFunction("finish");
}

if (file_exists($dataFile)) {
    unlink($dataFile);
}


/**
 * Prepares the setup for installing QUIQQER
 */
function prepareSetup()
{
    global $Setup, $data;

    \QUI\Setup\Log\Log::append("Preparing setup");

    $Setup->setData($data);
    $Setup->runSetup();
    $Setup->storeSetupState();

    continueWithStep("installquiqqer");
}

/**
 * Executes Composer to setup up QUIQQER
 */
function installQUIQQER()
{
    global $Setup, $data;

    \QUI\Setup\Log\Log::append("Installing QUIQQER");

    $Setup->restoreData();
    $data['salt'] = $Setup->getData()['salt'];
    $data['saltlength'] = $Setup->getData()['saltlength'];
    $data['rootGID'] = $Setup->getData()['rootGID'];
    $data['rootUID'] = $Setup->getData()['rootUID'];

    $Setup->setData($data);
    $Setup->runSetup(Setup::STEP_SETUP_INSTALL_QUIQQER);
    $Setup->storeSetupState();

    \QUI\Setup\Log\Log::append("QUIQQER Installation is done!");
    continueWithStep("setupquiqqer");
}

/**
 * Executes the setup routines after running composer
 */
function setupQUIQQER()
{
    global $Setup, $data;

    //Workaround
    if (!defined("QUIQQER_SETUP")) {
        define('QUIQQER_SETUP', true);
    }

    // Workaround to provide the correct data
    if (file_exists(dirname(__FILE__) . "/var/tmp/setup.json")) {
        $json = file_get_contents(dirname(__FILE__) . "/var/tmp/setup.json");
        $storedData = json_decode($json, true);
        $storedData['data']['user']['pw'] = $data['user']['pw'];
        file_put_contents(dirname(__FILE__) . "/var/tmp/setup.json", json_encode($storedData));
    }

    \QUI\Setup\Log\Log::append("Setting up QUIQQER");
    $Setup->restoreData();
    $Setup->runSetup(Setup::STEP_SETUP_QUIQQERSETUP);
    $Setup->storeSetupState();

    \QUI\Setup\Log\Log::append("QUIQQER Setup is done");

    continueWithStep("installpreset");
}

/**
 * Installs the packages associated with the preset and creates the project
 *
 * @param int $step - (optional) The step of the preset application process. Only relevant for the web setup!
 */
function installPreset($step = 1)
{
    global $Setup, $data;

    try {
        $Config = parse_ini_file(ETC_DIR . 'conf.ini.php', true);

        if ($Config === false) {
            writeStatus(1, "Could not parse config.");
        }

        $uid = $Config['globals']['rootuser'];
        $User = QUI::getUsers()->get($uid);

        // Read user authentication details from passwd file
        $passwd = $data['user']['pw'];

        QUI::getUsers()->login(
            $User->getUsername(),
            $passwd
        );

        $Setup->restoreData();
        $Setup->applyPreset($data['preset'], $step);
        $Setup->storeSetupState();
    } catch (\Exception $Exception) {
        echo "Error : " . $Exception->getMessage() . " <br />";
        @ob_flush();
        @flush();
    }

    if ($step == 1) {
        continueWithStep("installpreset2");
    }

    continueWithStep("setuppreset");
}

/**
 * Starts the setup process for the freshly installed presets
 */
function setupPreset()
{
    global $Setup, $data;

    \QUI\Setup\Log\Log::append("Setting up preset");

    $Setup->restoreData();
    $Setup->setupPreset();

    continueWithStep("lastsetup");
}

/**
 * Executes a javascript snippet to continue with the given step.
 */
function continueWithStep($step)
{
    if (isset($_REQUEST['language'])) {
        echo "<script>window.location='?step=" . $step . "&language=" . $_REQUEST['language'] . "'</script>";
    } else {
        echo "<script>window.location='?step=" . $step . "'</script>";
    }

    \QUI\Setup\Log\Log::append(
        "[" . date("H:i:s", time()) . "] " .
        "Memory peak usage in step '" . $_GET['step'] . "':" .
        number_format(memory_get_peak_usage(true), 0, ",", ".")
    ); // TODO DEBUG

    ob_flush();
    flush();
    exit;
}
