package hudson.plugins.jira;

import java.io.IOException;
import java.io.PrintStream;
import java.util.List;

import org.kohsuke.stapler.DataBoundConstructor;

import com.google.common.collect.Lists;

import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.matrix.MatrixAggregatable;
import hudson.matrix.MatrixAggregator;
import hudson.matrix.MatrixBuild;
import hudson.matrix.MatrixRun;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.plugins.jira.selector.AbstractIssueSelector;
import hudson.plugins.jira.selector.DefaultIssueSelector;
import hudson.scm.SCM;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Publisher;
import hudson.tasks.Recorder;
import jenkins.model.Jenkins;
import jenkins.tasks.SimpleBuildStep;

/**
 * Parses build changelog for JIRA issue IDs and then
 * updates JIRA issues accordingly.
 *
 * @author Kohsuke Kawaguchi
 */
public class JiraIssueUpdater extends Recorder implements MatrixAggregatable, SimpleBuildStep {

    private AbstractIssueSelector issueSelector;
    private SCM scm;
    private List<String> labels;

    @DataBoundConstructor
    public JiraIssueUpdater(AbstractIssueSelector issueSelector, SCM scm, List<String> labels) {
        super();
        this.issueSelector = issueSelector;
        this.scm = scm;
        if(labels != null)
            this.labels = labels;
        else
            this.labels = Lists.newArrayList();
    }

    @Override
    public void perform(Run<?, ?> run, FilePath workspace, Launcher launcher, TaskListener listener) throws InterruptedException, IOException {
        // Don't do anything for individual matrix runs.
        if (run instanceof MatrixRun) {
            return;
        } else if(run instanceof AbstractBuild) {
            AbstractBuild<?,?> abstractBuild = (AbstractBuild<?,?>) run;
            Updater updater = new Updater(abstractBuild.getParent().getScm(), labels);
            updater.perform(run, listener, getIssueSelector());
        } else if(scm != null) {
            Updater updater = new Updater(scm, labels);
            updater.perform(run, listener, getIssueSelector());
        } else {
            throw new IllegalArgumentException("Unsupported run type "+run.getClass().getName());
        }
    }

    public BuildStepMonitor getRequiredMonitorService() {
        return BuildStepMonitor.BUILD;
    }

    public void setIssueSelector(AbstractIssueSelector issueSelector) {
        this.issueSelector = issueSelector;
    }

    public SCM getScm() {
        return scm;
    }

    public void setScm(SCM scm) {
        this.scm = scm;
    }

    public List<String> getLabels() {
        return labels;
    }

    public void setLabels(List<String> labels) {
        this.labels = labels;
    }


    @Override
    public DescriptorImpl getDescriptor() {
        return DESCRIPTOR;
    }

    public AbstractIssueSelector getIssueSelector() {
        AbstractIssueSelector uis = this.issueSelector;
        if (uis == null) uis = new DefaultIssueSelector();
        return (this.issueSelector = uis);
    }

    @Extension
    public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();

    public MatrixAggregator createAggregator(MatrixBuild build, Launcher launcher, BuildListener listener) {
        return new MatrixAggregator(build, launcher, listener) {
            @Override
            public boolean endBuild() throws InterruptedException, IOException {
                PrintStream logger = listener.getLogger();
                logger.println("End of Matrix Build. Updating JIRA.");
                Updater updater = new Updater(this.build.getParent().getScm(), labels);
                return updater.perform(this.build, this.listener, getIssueSelector());
            }
        };
    }

    public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> {
        private DescriptorImpl() {
            super(JiraIssueUpdater.class);
        }

        @Override
        public String getDisplayName() {
            // Displayed in the publisher section
            return Messages.JiraIssueUpdater_DisplayName();

        }

        @Override
        public String getHelpFile() {
            return "/plugin/jira/help.html";
        }

        @Override
        @SuppressWarnings("unchecked")
        public boolean isApplicable(Class<? extends AbstractProject> jobType) {
            return true;
        }

        public boolean hasIssueSelectors() {
            return Jenkins.getActiveInstance().getDescriptorList(AbstractIssueSelector.class).size() > 1;
        }
    }

}

@@ -2929,17 +2929,16 @@
 %0A    %7D%0A%0A
-%0A
     @Ove

removing blank line