package io.blueocean.ath.offline.multibranch;

import com.google.common.io.Files;
import com.google.common.io.Resources;
import io.blueocean.ath.ATHJUnitRunner;
import io.blueocean.ath.GitRepositoryRule;
import io.blueocean.ath.WaitUtil;
import io.blueocean.ath.api.classic.ClassicJobApi;
import io.blueocean.ath.factory.MultiBranchPipelineFactory;
import io.blueocean.ath.model.MultiBranchPipeline;
import org.apache.log4j.Logger;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.junit.*;
import org.junit.runner.RunWith;
import org.openqa.selenium.By;

import javax.inject.Inject;
import java.io.File;
import java.io.IOException;
import java.net.URL;

@RunWith(ATHJUnitRunner.class)
public class ParallelNavigationTest {

    private Logger logger = Logger.getLogger(CommitMessagesTest.class);

    @Rule
    @Inject
    public GitRepositoryRule git;

    @Inject
    ClassicJobApi jobApi;

    @Inject
    WaitUtil wait;

    @Inject
    MultiBranchPipelineFactory mbpFactory;

    // Names of the pipelines we'll create
    String navTest          = "ParallelNavTest_tested";
    String navTestWithInput = "ParallelNavTestWithInput_tested";

    // Initialize our MultiBranchPipeline objects
    static MultiBranchPipeline navTestPipeline = null;
    static MultiBranchPipeline navTestWithInputPipeline = null;

    // Create the pipelines in a @Before, instead of in each individual test
    @Before
    public void setupPipelines () throws IOException, GitAPIException, InterruptedException {
        // Create navTest
        logger.info("Creating pipeline " + navTest);
        URL navTestJenkinsfile = Resources.getResource(ParallelNavigationTest.class, "ParallelNavigationTest/Jenkinsfile");
        Files.copy(new File(navTestJenkinsfile.getFile()), new File(git.gitDirectory, "Jenkinsfile"));
        git.addAll();
        git.commit("Initial commit for " + navTest);
        logger.info("Committed Jenkinsfile for " + navTest);
        navTestPipeline = mbpFactory.pipeline(navTest).createPipeline(git);
        logger.info("Finished creating " + navTest);

        // Create navTestWithInput
        logger.info("Creating pipeline " + navTestWithInput);
        URL navTestInputJenkinsile = Resources.getResource(ParallelNavigationTest.class, "ParallelNavigationTest/Jenkinsfile.input");
        Files.copy(new File(navTestInputJenkinsile.getFile()), new File(git.gitDirectory, "Jenkinsfile"));
        git.addAll();
        git.commit("Initial commit for " + navTestWithInput);
        logger.info("Committed Jenkinsfile for " + navTestWithInput);
        navTestWithInputPipeline = mbpFactory.pipeline(navTestWithInput).createPipeline(git);
        logger.info("Finished creating " + navTestWithInput);
    }

    /**
     * This checks that we can run a pipeline with 2 long running parallel branches.
     * You should be able to click between one and the other and see it progressing.
     */
    @Test
    public void parallelNavigationTest () throws IOException, GitAPIException, InterruptedException {
        logger.info("Beginning parallelNavigationTest()");
        navTestPipeline.getRunDetailsPipelinePage().open(1);
        // At first we see branch one
        wait.until(By.xpath("//*[text()=\"firstBranch\"]"));
        logger.info("Found first branch");
        // and clicking on the unselected node will yield us the second branch
        wait.click(By.xpath("//*[contains(@class, 'pipeline-node')][3]"));
        wait.until(By.xpath("//*[text()=\"secondBranch\"]"));
        logger.info("Found second branch");
    }

    /**
     * This checks that you can have input on 2 different parallel branches. There are no stages either side of the parallel construct.
     * One at a time, the proceed button will be clicked.
     */
    @Test
    public void parallelNavigationTestInput () throws IOException, GitAPIException, InterruptedException {
        logger.info("Beginning parallelNavigationTestInput()");
        navTestWithInputPipeline.getRunDetailsPipelinePage().open(1);
        // At first we see branch one
        wait.until(By.xpath("//*[text()=\"firstBranch\"]"));
        logger.info("Found first branch");
        wait.click(By.cssSelector(".btn.inputStepSubmit"));
        logger.info("Clicked the inputStepSubmit button");
        // And clicking on the unselected node will yield us the second branch
        wait.click(By.xpath("//*[contains(@class, 'pipeline-node')][3]"));
        wait.until(By.xpath("//*[text()=\"secondBranch\"]"));
        logger.info("Found second branch");
        wait.click(By.cssSelector(".btn.inputStepSubmit"));
        logger.info("Clicked the inputStepSubmit button");

    }

    @AfterClass
    public static void deleteTestPipelines() throws IOException, GitAPIException, InterruptedException {
        MultiBranchPipeline[] listOfPipelineJobs = {navTestPipeline, navTestWithInputPipeline};
        for (MultiBranchPipeline pipelineToCleanup:listOfPipelineJobs) {
            /*
            stopAllRuns and deleteThisPipeline both provide their own
            logger messages, no need to create new ones here.
            */
            pipelineToCleanup.stopAllRuns();
            pipelineToCleanup.deleteThisPipeline(pipelineToCleanup.getName());
        }
    }
}

@@ -193,24 +193,55 @@
 sitoryRule;%0A
+import io.blueocean.ath.Retry;%0A
 import io.bl
@@ -2952,32 +2952,46 @@
    */%0A    @Test%0A
+    @Retry(3)%0A
     public void 
@@ -4724,21 +4724,16 @@
   @After
-Class
 %0A    pub
@@ -4736,23 +4736,16 @@
  public 
-static 
 void del

add a retry and cleanup between runs (#1612)