<?php

namespace BtwInstaller;

class BlueTwilightInstaller
{
    private $baseDirectory;
    private $composerSignature;

    public function __construct()
    {
        $this->baseDirectory = dirname(__DIR__);
        chdir($this->baseDirectory);
        putenv('HOME=' . $this->baseDirectory);

        // Display errors so installer never gets a WSOD!
        ini_set('display_errors', true);
    }

    public function run()
    {
        if (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST')
        {
            // Handle post
            $this->runInstall();
            exit();
        }
?>
        <html>
        <head>
            <title>Blue Twilight Setup</title>
        </head>
        <body>
            <h1>Blue Twilight Setup</h1>
            <p>We need to download a few things - namely <a href="http://getcomposer.org" target="_blank">Composer</a> and related packages - before we can kick off the Blue Twilight installer.</p>
            <p>We can do this for you - simply click the button below.</p>
            <p style="font-weight: bold; color: #ff0000;">This can take a few minutes so please be patient, and only click the button once!</p>
            <form method="post">
                <button type="submit">Install Composer and dependencies for me</button>
            </form>

            <hr/>
            <h2>Got Composer?</h2>

            <p>If you already have Composer installed, however, you may want to use that instead. Just run the below commands on your server, changing the path to Composer as appropriate:</p>
            <p><em>Please note: &quot;composer.phar&quot; may actually be &quot;composer&quot; on your system.</em></p>
            <pre>cd <?php echo $this->baseDirectory; ?><br/>/path/to/composer.phar install</pre>
        </body>
        </html>
<?php
    }

    private function runInstall()
    {

?>
        <h1>Installing Blue Twilight Setup Files</h1>

        <ul>
<?php
        $steps = [
            ['Checking PHP modules', 'checkPhpModules'],
            ['Fetching Composer signature', 'fetchComposerSignature'],
            ['Installing Composer', 'installComposer'],
            ['Installing dependencies using Composer', 'runComposer'],
            ['Generating application key', 'generateAppKey']
        ];

        $successful = true;
        foreach ($steps as $step)
        {
            echo sprintf("<li>%s...</li>%s", $step[0], PHP_EOL);
            $result = call_user_func([$this, $step[1]]);

            if (!$result)
            {
                $successful = false;
                break;
            }
        }

        if ($successful)
        {
            header('Location: install/check');
            exit();
        }

?>
        </ul>
<?php
    }

    private function checkPhpModules()
    {
        $requiredModules = [
            'simplexml',
            'curl',
            'mbstring',
            'dom'
        ];
        $invalidModules = [];

        foreach ($requiredModules as $module)
        {
            if (!extension_loaded($module))
            {
                $invalidModules[] = $module;
            }
        }

        if (count($invalidModules) > 0)
        {
            $this->echoError(sprintf('The following PHP modules are missing and need to be installed to continue: %s', join(', ', $invalidModules)));
            return false;
        }

        return true;
    }

    private function echoError($message)
    {
        echo sprintf("<span style=\"color: #ff0000;\">%s.</span>%s", $message, PHP_EOL);
    }

    private function echoOK($message = '')
    {
        echo "<span style=\"color: #008800;\">OK";

        if (strlen($message) > 0)
        {
            echo sprintf('... %s', $message);
        }

        echo '</span>' . PHP_EOL;
    }

    private function fetchComposerSignature()
    {
        if (!boolval(ini_get('allow_url_fopen')))
        {
            $this->echoError('allow_url_fopen is disabled so we cannot use Composer');
            echo '<br/>';
            $this->echoError('You will need to install the vendor libraries manually - <a href="https://github.com/pandy06269/blue-twilight/wiki/Install-Vendor-libraries-manually" target="_blank">see this page for more details</a>');
            return false;
        }

        $signatureUrl = 'https://composer.github.io/installer.sig';
        $this->composerSignature = trim(file_get_contents($signatureUrl));
        if (strlen($this->composerSignature) == 0)
        {
            $this->echoError(sprintf("Failed downloading the Composer signature from %s", $signatureUrl));
            return false;
        }
        else
        {
            $this->echoOK($this->composerSignature);
        }

        return true;
    }

    private function generateAppKey()
    {
        if (!file_exists('.env') && file_exists('.env.example'))
        {
            copy('.env.example', '.env');
        }

        ob_start();
        system('touch .env', $rc);
        $result = ob_get_clean();
        echo nl2br($result);

        ob_start();
        system('php artisan key:generate', $rc);
        $result = ob_get_clean();
        echo nl2br($result);

        if ($rc != 0)
        {
            $this->echoError('Failed to generate application key');
            return false;
        }

        $this->echoOK();
        return true;
    }

    private function installComposer()
    {
        $rc = -1;

        ob_start();
        system('php -r "copy(\'https://getcomposer.org/installer\', \'composer-setup.php\');"', $rc);
        $result = ob_get_clean();
        echo nl2br($result);

        if ($rc != 0)
        {
            $this->echoError('Failed to fetch Composer');
            return false;
        }

        ob_start();
        system(sprintf('php -r "if (hash_file(\'SHA384\', \'composer-setup.php\') === \'%s\') { echo \'Installer verified\'; } else { echo \'Installer corrupt\'; unlink(\'composer-setup.php\'); } echo PHP_EOL;"', $this->composerSignature), $rc);
        $result = ob_get_clean();
        echo nl2br($result);
        if ($rc != 0)
        {
            $this->echoError('Composer verification failed');
            return false;
        }

        ob_start();
        system('php composer-setup.php', $rc);
        $result = ob_get_clean();
        echo nl2br($result);
        if ($rc != 0)
        {
            $this->echoError('Failed to install Composer');
            return false;
        }

        ob_start();
        system('php -r "unlink(\'composer-setup.php\');"', $rc);
        $result = ob_get_clean();
        echo nl2br($result);
        if ($rc != 0)
        {
            $this->echoError('Failed to remove Composer setup file');
            return false;
        }

        $this->echoOK();
        return true;
    }

    private function runComposer()
    {
        ob_start();
        system('php composer.phar install', $rc);
        $result = ob_get_clean();
        echo nl2br($result);
        if ($rc != 0)
        {
            $this->echoError('Installing Composer packages failed');
            return false;
        }

        $this->echoOK();
        return true;
    }
}

$installer = new BlueTwilightInstaller();
$installer->run();