<?php

class VcsApi
{
    protected $username = '';
    protected $gitServer = '';
    protected $gitBranch = '';
    protected $vcsSettings = null;
    public const GIT_TYPE = 'GIT';
    public const CFBS_TYPE = 'GIT_CFBS';
    public const VCS_TYPES = [self::GIT_TYPE, self::CFBS_TYPE];

    public function __construct($data = array())
    {
        $this->vcsSettings = new VcsSettingsLib();

        if (! empty($data)) {

            $this->initialize($data);
        }
    }

    public function initialize($config = array())
    {

        syslog(LOG_DEBUG, 'Initializing VCSAPI...');


        foreach ($config as $key => $val) {
            if (isset($this->$key)) {
                $method = 'set_' . $key;

                if (method_exists($this, $method)) {
                    $this->$method($val);
                } else {
                    $this->$key = $val;
                    syslog(LOG_DEBUG, sprintf("setting %s => %s in git service class", $key, $val));
                }
            }
        }
    }

    /**
     * @param $data
     *
     * @throws Exception
     */
    public function generateUpdateScripts($data)
    {
        syslog(LOG_DEBUG, 'Initializing git clone for staging area..');
        try {
            $this->generateScriptFromTemplates('params.template', 'params.sh', $data);
        } catch (Exception $e) {
            syslog(LOG_ERR, 'Update script generating error: ' . $e->getMessage());
            throw new Exception('Update script generating error: ' . $e->getMessage());
        }
    }

    public function writePrivateKey($data)
    {
        try {
            $fullPath = $this->vcsSettings->get_user_ssh_key_path();
            ;
            if (file_put_contents($fullPath, $data) !== false) {
                chmod($fullPath, 0600);
            } else {
                throw new Exception("Error uploading file Request", 1);
            }
        } catch (Exception $e) {
            $msg = $e->getMessage();
            syslog(LOG_ERR, "Cannot write private key to $fullPath. Error: $msg");
            throw $e;
        }
    }


    /**
     * @param $templateName
     * @param $filename
     * @param $data
     *
     * @throws Exception
     */
    public function generateScriptFromTemplates($templateName, $filename, $data)
    {
        $scriptTemplatePath = $this->vcsSettings->get_dc_update_script_template_path() . DIRECTORY_SEPARATOR . $templateName;
        $templateContent    = @file_get_contents($scriptTemplatePath);
        if ($templateContent === false) {
            syslog(LOG_ERR, "Template for $templateName script not found at path:" . $scriptTemplatePath);

            throw new Exception("Cannot get the content of the $templateName script template to generate the script from path $scriptTemplatePath");
        } else {
            $replace         = $this->getScriptTemplateParameters($data);
            $generatedScript = str_replace(array_keys($replace), array_values($replace), $templateContent);
            $scriptPath      = $this->vcsSettings->get_dc_update_script_path() . DIRECTORY_SEPARATOR . $filename;
            syslog(LOG_DEBUG, "writing $templateName script at path: $scriptPath");

            $result = @file_put_contents($scriptPath, $generatedScript);
            if ($result === false) {
                syslog(LOG_ERR, "cannot write $filename script at path: $scriptPath");

                throw new Exception("Cannot generate $filename script file at $scriptPath");
            } else {
                chmod($scriptPath, 0750);
            }
        }
    }

    /**
     * @param $data
     *
     * @return array
     */
    public function getScriptTemplateParameters($data)
    {
        $vcsType      = $data['vcsType'] ?? '';
        $gitServerUrl = $data['gitServer'] ?? '';
        $gitRefspec   = $data['gitRefspec'] ?? '';
        $projectSubdirectory = $data['projectSubdirectory'] ?? '';
        $gitUsername  = $data['gitUsername'] ?? '';
        $gitPassword  = $data['gitPassword'] ?? '';
        $buildProject  = $data['buildProject'] ?? '';

        $keyPath               = isset($data['gitPrivateKey']) ? $this->vcsSettings->get_dc_user_ssh_key() : '';
        $workDir               = $this->vcsSettings->get_dc_staging_repository();
        $gitLocalWorkingBranch = $this->vcsSettings->get_dc_git_working_branch();
        $scriptDir             = $this->vcsSettings->get_dc_update_script_template_path();

        $replace = array(
            '%WORKING_DIR%'      => $workDir,
            '%REMOTE_GIT_URL%'   => $gitServerUrl,
            '%GIT_REFSPEC%'      => $gitRefspec,
            '%PROJECT_SUBDIRECTORY%' => $projectSubdirectory,
            '%GIT_USERNAME%'     => $gitUsername,
            '%GIT_PASSWORD%'     => $gitPassword,
            '%LOCAL_GIT_BRANCH%' => $gitLocalWorkingBranch,
            '%SSH_PRIVATE_KEY%'  => $keyPath,
            '%VCS_TYPE%'         => $vcsType,
            '%SCRIPT_DIR%'       => $scriptDir,
            '%BUILD_PROJECT%'       => $buildProject,
        );

        foreach ($replace as $key => $val) {
            $replace[$key] = '"' . str_replace('"', '\"', $val) . '"';
        }

        return $replace;
    }

}

class DC_Exception extends Exception
{
}

class DC_Settings_Exception extends DC_Exception
{
}

; // when settings are not specified
class DC_Staging_Notfound_Exception extends DC_Exception
{
}

;

class Git_Settings_Exception extends DC_Exception
{
}

; // related to git errors
