<?php

\define("NO_KEEP_STATISTIC", true);
\define("NOT_CHECK_PERMISSIONS",true);
\define('CHK_EVENT', true);
\define("NO_AGENT_CHECK", true);
\define("LANGUAGE_ID", 'en');

@\set_time_limit(0);
@\ignore_user_abort(true);

use \Bitrix\Main\{
    IO,
    Application,
    Web,
    Localization
};

$_SERVER["DOCUMENT_ROOT"] = \realpath(__DIR__);
$DOCUMENT_ROOT = $_SERVER["DOCUMENT_ROOT"];

require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php");
require_once(Application::getDocumentRoot() . "/bitrix/modules/main/classes/general/update_client.php");

Localization\Loc::loadMessages(Application::getDocumentRoot() . '/bitrix/modules/main/admin/update_system_call.php');

class AutoUpdater{
    protected $options = [
        'stable' => 'Y',
        'moduleList' => [],
        'loopLimit' => 10000,
    ];

    protected $updateList = [];
    protected $iterator = 0;

    public function __construct(){
        $moduleDirectory = new IO\Directory(Application::getDocumentRoot() . "/bitrix/modules");
        foreach($moduleDirectory->getChildren() as $entity){
            if($entity->isDirectory() && \count(\explode('.', $entity->getName())) == 1){
                $this->options['moduleList'][] = $entity->getName();
            }
        }
    }

    public function getUpdateList(){
        return $this->updateList;
    }

    public function setStable(bool $stable){
        $this->options['stable'] = $stable ?'Y' :'N';
    }

    public function update(){
        while(true){
            if($this->iterator++ >= $this->options['loopLimit']){
                throw new \Exception('Reached Loop Limit [17082019.0038.1]');
            }

            $errorMessage = '';

            // Get description
            $loadResult = \CUpdateClient::LoadModulesUpdates($errorMessage, $descriptionList, LANG, $this->options['stable'], $this->options['moduleList']);
            if(!empty($errorMessage)){
                throw new \Exception(\sprintf('%s [17082019.0051.1]', $errorMessage), 500);
            }

            if(isset($descriptionList["DATA"]["#"]["ITEM"])) {
                for($i = 0, $cnt = \count($descriptionList["DATA"]["#"]["ITEM"]); $i < $cnt; $i++){
                    $this->updateList[] = [
                        'name' => $descriptionList["DATA"]["#"]["ITEM"][$i]["@"]["NAME"],
                        'value' => $descriptionList["DATA"]["#"]["ITEM"][$i]["@"]["VALUE"],
                    ];
                }
            }

            // Get archive
            if($loadResult == "S"){
                $loadResult = \CUpdateClient::LoadModulesUpdates($errorMessage, $descriptionList, LANG, $this->options['stable'], $this->options['moduleList']);
            }

            if($loadResult == "E"){
                if(\mb_strlen($errorMessage) <= 0){
                    throw new \Exception(\sprintf('%s [16082019.0354.1]', Localization\Loc::getMessage("SUPC_ME_PACK")), 500);
                }
            }
            elseif($loadResult == "F"){
                throw new \Exception('ok', 200);
            }

            // Unzip
            if(\mb_strlen($errorMessage) <= 0){
                $updateDirectory = "";
                if(!\CUpdateClient::UnGzipArchive($updateDirectory, $errorMessage, true)){
                    throw new \Exception(\sprintf('%s [16082019.0355.1]', Localization\Loc::getMessage("SUPC_ME_PACK")), 500);
                }
            }

            // Validation
            if(!\CUpdateClient::CheckUpdatability($updateDirectory, $errorMessage)) {
                throw new \Exception(\sprintf('%s [16082019.0356.1]', Localization\Loc::getMessage("SUPC_ME_CHECK")), 500);
            }

            // Run update
            if(!\CUpdateClient::UpdateStepModules($updateDirectory, $errorMessage)){
                throw new \Exception(\sprintf('%s [16082019.0357.1]', Localization\Loc::getMessage("SUPC_ME_UPDATE")), 500);
            }

            // Finalize
            \CUpdateClient::finalizeModuleUpdate($descriptionList["DATA"]["#"]["ITEM"]);
        }
    }
}

$response = [];
try{
    $updater = new \AutoUpdater();
    $updater->setStable(false);
    $updater->update();
}
catch(\Exception $e){
    $response['message'] = $e->getMessage();
    $response['code'] = $e->getCode();
    $response['updates'] = $updater ?$updater->getUpdateList(): [];
}

echo Web\Json::encode($response);

$updateFile = new IO\File(__FILE__);
$updateFile->delete();
