package core;
/*
 * This file is part of the TYPO3 CMS project.
 *
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, either version 2
 * of the License, or any later version.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 *
 * The TYPO3 project - inspiring people to share!
 */

import com.atlassian.bamboo.specs.api.builders.BambooKey;
import com.atlassian.bamboo.specs.api.builders.plan.Job;
import com.atlassian.bamboo.specs.api.builders.plan.Stage;
import com.atlassian.bamboo.specs.api.builders.plan.branches.BranchCleanup;
import com.atlassian.bamboo.specs.api.builders.plan.branches.PlanBranchManagement;
import com.atlassian.bamboo.specs.api.builders.project.Project;
import com.atlassian.bamboo.specs.builders.task.ScriptTask;
import com.atlassian.bamboo.specs.builders.trigger.RemoteTrigger;
import com.atlassian.bamboo.specs.model.task.ScriptTaskProperties;

import java.util.ArrayList;

/**
 * Pre-Merge and Security Pre-Merge tests use the same setup, but different repositories and triggers
 * Bundling the common bits in a parent class eases changes in the future
 */
abstract class AbstractPreMergeSpec extends AbstractCoreSpec {

    private static int numberOfAcceptanceTestJobs = 8;
    private static int numberOfFunctionalMysqlJobs = 10;
    private static int numberOfFunctionalPgsqlJobs = 10;
    private static int numberOfUnitRandomOrderJobs = 1;
    private static int numberOfFunctionalMssqlJobs = 10;
    Boolean isSecurity = true;
    private String[] phpVersions = {"PHP70", "PHP71", "PHP72", "PHP73", "PHP74"};

    /**
     * Core 8.7 plans are in "TYPO3 core" project of bamboo
     */
    protected Project project() {
        return new Project().name(projectName).key(projectKey);
    }

    Stage getMainStage() {
        ArrayList<Job> jobsMainStage = new ArrayList<Job>();

        jobsMainStage.add(this.getJobAcceptanceTestInstallMysql(phpVersions[3], isSecurity));
        jobsMainStage.add(this.getJobAcceptanceTestInstallMysql(phpVersions[4], isSecurity));
        jobsMainStage.add(this.getJobAcceptanceTestInstallPgsql(phpVersions[2], isSecurity));

        jobsMainStage.addAll(this.getJobsAcceptanceTestsBackendMysql(numberOfAcceptanceTestJobs, phpVersions[2], isSecurity));

        jobsMainStage.add(this.getJobIntegrationVarious(phpVersions[2], isSecurity));

        jobsMainStage.addAll(this.getJobsFunctionalTestsMysql(numberOfFunctionalMysqlJobs, phpVersions[2], isSecurity));
        jobsMainStage.addAll(this.getJobsFunctionalTestsMysql(numberOfFunctionalMysqlJobs, phpVersions[4], isSecurity));
        // mssql functionals are not executed as pre-merge
        // jobsMainStage.addAll(this.getJobsFunctionalTestsMssql(this.numberOfFunctionalMssqlJobs, "PHP72", isSecurity));
        jobsMainStage.addAll(this.getJobsFunctionalTestsPgsql(numberOfFunctionalPgsqlJobs, phpVersions[3], isSecurity));

        jobsMainStage.add(this.getJobUnitJavaScript(phpVersions[2], isSecurity));
        jobsMainStage.add(this.getJobLintScssTs(phpVersions[2], isSecurity));

        for (String phpVersion : phpVersions) {
            jobsMainStage.add(this.getJobLintPhp(phpVersion, isSecurity));
            jobsMainStage.add(this.getJobUnitPhp(phpVersion, isSecurity));
            jobsMainStage.addAll(this.getJobUnitPhpRandom(numberOfUnitRandomOrderJobs, phpVersion, isSecurity));
        }

        return new Stage("Main stage")
            .jobs(jobsMainStage.toArray(new Job[jobsMainStage.size()]));
    }

    RemoteTrigger getGithubTrigger() {
        return new RemoteTrigger()
            .name("Remote trigger for pre-merge builds")
            .description("Github")
            .triggerIPAddresses("192.30.252.0/22,185.199.108.0/22,140.82.112.0/20,172.18.0.1/24");
    }

    PlanBranchManagement getBranchManagement() {
        return new PlanBranchManagement()
            .createForVcsBranch()
            .delete(new BranchCleanup()
                .whenRemovedFromRepositoryAfterDays(1))
            .notificationForCommitters()
            .issueLinkingEnabled(false);
    }

    Stage getEarlyStage() {
        ArrayList<Job> jobsEarlyStage = new ArrayList<Job>();
        jobsEarlyStage.add(this.getJobCglCheckGitCommit(phpVersions[2], isSecurity));
        jobsEarlyStage.add(this.getJobComposerValidate(phpVersions[2], isSecurity));
        return new Stage("Early")
            .jobs(jobsEarlyStage.toArray(new Job[jobsEarlyStage.size()]));
    }

    /**
     * Job checking CGL of last git commit
     */
    Job getJobCglCheckGitCommit(String requirementIdentifier, Boolean isSecurity) {
        return new Job("Integration CGL", new BambooKey("CGLCHECK"))
            .description("Check coding guidelines by executing Build/Scripts/cglFixMyCommit.sh script")
            .pluginConfigurations(this.getDefaultJobPluginConfiguration())
            .tasks(
                this.getTaskGitCloneRepository(),
                this.getTaskStopDanglingContainers(),
                this.getTaskComposerInstall(requirementIdentifier),
                new ScriptTask()
                    .description("Execute cgl check script")
                    .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                    .inlineBody(
                        this.getScriptTaskBashInlineBody() +
                            "function cglFixMyCommit() {\n" +
                            "    docker run \\\n" +
                            "        -u ${HOST_UID} \\\n" +
                            "        -v /bamboo-data/${BAMBOO_COMPOSE_PROJECT_NAME}/passwd:/etc/passwd \\\n" +
                            "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
                            "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
                            "        --rm \\\n" +
                            "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
                            "        bin/bash -c \"cd ${PWD}; ./Build/Scripts/cglFixMyCommit.sh $*\"\n" +
                            "}\n" +
                            "\n" +
                            "cglFixMyCommit dryrun\n"
                    )
            )
            .requirements(
                this.getRequirementDocker10()
            )
            .cleanWorkingDirectory(true);
    }
}
