package com.groupon.jenkins.dynamic.build.api.metrics;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.groupon.jenkins.SetupConfig;
import com.groupon.jenkins.dynamic.build.DynamicProject;
import com.groupon.jenkins.extensions.DotCiExtension;
import com.mongodb.DB;
import hudson.ExtensionPoint;
import jenkins.model.Jenkins;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;

import javax.annotation.Nullable;
import java.util.List;

@ExportedBean
public abstract class JobMetric implements ExtensionPoint {

    private DynamicProject project;
    private String branch;
    private int buildCount;

    @Exported(inline = true)
    public abstract Chart getChart();

    protected DB getDB() {
        return SetupConfig.get().getDynamicBuildRepository().getDatastore().getDB();
    }

    @Exported(inline = true)
    public abstract String getName();

    public abstract boolean isApplicable();

    public static List<JobMetric> getJobMetrics(DynamicProject project, String branch, int buildCount) {
        List<JobMetric> jobMetrics = Jenkins.getInstance().getExtensionList(JobMetric.class);
        for (JobMetric metric : jobMetrics) {
            metric.setProject(project);
            metric.setBranch(branch);
            metric.setBuildCount(buildCount);
        }
        return jobMetrics;
    }

    private void setProject(DynamicProject project) {
        this.project = project;
    }

    public DynamicProject getProject() {
        return project;
    }

    public static List<JobMetric> getApplicableJobMetrics(DynamicProject dynamicProject, String branch, int buildCount) {
        return Lists.newArrayList( Iterables.filter(getJobMetrics(dynamicProject,branch,buildCount), new Predicate<JobMetric>() {
            @Override
            public boolean apply(JobMetric metric) {
                return metric.isApplicable();
            }
        }));
    }

    public void setBranch(String branch) {
        this.branch = branch;
    }

    public void setBuildCount(int buildCount) {
        this.buildCount = buildCount;
    }
    public int getBuildCount() {
        return buildCount;
    }

    public String getBranch() {
        return branch;
    }
}

@@ -260,75 +260,240 @@
 ld.D
-ynamicProject;%0Aimport com.groupon.jenkins.extensions.DotCiExtension
+bBackedBuild;%0Aimport com.groupon.jenkins.dynamic.build.DbBackedProject;%0Aimport com.groupon.jenkins.dynamic.build.DynamicBuild;%0Aimport com.groupon.jenkins.dynamic.build.DynamicProject;%0Aimport com.groupon.jenkins.util.GReflectionUtils
 ;%0Aim
@@ -543,16 +543,41 @@
 nPoint;%0A
+import hudson.model.Run;%0A
 import j
@@ -694,64 +694,102 @@
 an;%0A
-%0A
 import 
-javax.annotation.Nullable;%0Aimport java.util.List
+org.mongodb.morphia.query.Query;%0A%0Aimport java.util.List;%0Aimport java.util.regex.Pattern
 ;%0A%0A@
@@ -1625,32 +1625,33 @@
 unt);%0A        %7D%0A
+%0A
         return j
@@ -1649,16 +1649,17 @@
  return 
+ 
 jobMetri
@@ -2541,10 +2541,1699 @@
 ;%0A    %7D%0A
+    protected List%3CDynamicBuild%3E getBuilds(Query%3CDynamicBuild%3E query) %7B%0A        query = applyQueryValues(query);%0A        query = applyQueryValues(query);%0A%0A        List%3CDynamicBuild%3E builds = query.asList();%0A        for(DynamicBuild build: builds)%7B%0A            associateProject(getProject(),build);%0A        %7D%0A        return builds;%0A    %7D%0A    protected Query%3CDynamicBuild%3E getQuery(DbBackedProject project) %7B%0A        return SetupConfig.get().getDynamicBuildRepository().getDatastore().createQuery(DynamicBuild.class).disableValidation().field(%22projectId%22).equal(project.getId());%0A    %7D%0A    private Query%3CDynamicBuild%3E applyQueryValues(Query%3CDynamicBuild%3E query) %7B%0A        query = filterBranch(query);%0A        query = query.limit(getBuildCount());%0A        return query.order(%22-number%22);%0A    %7D%0A    private Query%3CDynamicBuild%3E filterBranch(Query%3CDynamicBuild%3E query) %7B%0A        String branch = getBranch();%0A        if(%22All%22.equals(branch))%7B%0A            return query;%0A        %7D%0A        if(%22Mine%22.equals(branch))%7B%0A            query.or(%0A                    query.criteria(%22actions.causes.user%22).equal(Jenkins.getAuthentication().getName()),%0A                    query.criteria(%22actions.causes.pusher%22).equal(Jenkins.getAuthentication().getName())%0A            );%0A            return query;%0A        %7D%0A%0A%0A        Pattern branchRegex = Pattern.compile(branch);%0A        query = query.filter(%22actions.causes.branch.branch%22, branchRegex);%0A        return query;%0A    %7D%0A    private void associateProject(DbBackedProject project, DbBackedBuild build) %7B%0A        if(build != null) %7B%0A            GReflectionUtils.setField(Run.class, %22project%22, build, project);%0A            build.postMorphiaLoad();%0A        %7D%0A    %7D%0A%0A
 %7D%0A

Move helper methods up into base class