package hudson.plugins.sectioned_view;

import hudson.Extension;
import hudson.model.Descriptor;
import hudson.model.HealthReport;
import hudson.model.Hudson;
import hudson.model.Item;
import hudson.model.Job;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.Saveable;
import hudson.model.TopLevelItem;
import hudson.model.View;
import hudson.model.ViewDescriptor;
import hudson.model.Descriptor.FormException;
import hudson.util.DescribableList;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.servlet.ServletException;

import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

public class SectionedView extends View {

	private DescribableList<SectionedViewSection, Descriptor<SectionedViewSection>> sections;

	public Iterable<SectionedViewSection> getSections() {
		return sections;
	}

	@DataBoundConstructor
	public SectionedView(String name) {
		super(name);
		initSections();
	}

	protected void initSections() {
		if (sections != null) {
			// already persisted
			return;
		}

		sections = new DescribableList<SectionedViewSection, Descriptor<SectionedViewSection>>(
				Saveable.NOOP);
	}

	public static Collection<Job> sortJobs(Collection<Job> jobs) {
		TreeSet<Job> set = new TreeSet<Job>(new JobComparator());
		if (jobs != null) {
			set.addAll(jobs);
		}
		return set;
	}

	public static boolean isBuilding(Job job) {
		Run lastBuild = job.getLastBuild();
		return lastBuild != null
				&& (lastBuild.isLogUpdated() || lastBuild.isBuilding());
	}

	private static final class JobComparator implements Comparator<Job> {
		public int compare(Job o1, Job o2) {
			// first compare by status
			Result r1 = getResult(o1);
			Result r2 = getResult(o2);
			if (r1 != null && r2 != null) {
				if (r1.isBetterThan(r2)) {
					return 1;
				} else if (r1.isWorseThan(r2)) {
					return -1;
				}
			}

			HealthReport h1 = o1.getBuildHealth();
			HealthReport h2 = o2.getBuildHealth();
			if (h1 != null && h2 != null) {
				// second compare by stability
				int health = h1.compareTo(h2);
				if (health != 0) {
					return health;
				}
			}

			// finally compare by name
			return o1.getName().compareTo(o2.getName());
		}
	}

	public static Result getResult(Job job) {
		Run lastBuild = job.getLastBuild();
		while (lastBuild != null
				&& (lastBuild.hasntStartedYet() || lastBuild.isBuilding() || lastBuild
						.isLogUpdated())) {
			lastBuild = lastBuild.getPreviousBuild();
		}
		if (lastBuild != null) {
			return lastBuild.getResult();
		} else {
			return Result.NOT_BUILT;
		}
	}

	/**
	 * Handles the configuration submission.
	 * 
	 * Load view-specific properties here.
	 */
	@Override
	protected void submit(StaplerRequest req) throws ServletException,
			FormException {
		if (sections == null) {
			sections = new DescribableList<SectionedViewSection, Descriptor<SectionedViewSection>>(
					Saveable.NOOP);
		}
		sections.rebuildHetero(req, req.getSubmittedForm(), Hudson
				.getInstance().getDescriptorList(SectionedViewSection.class),
				"sections");
	}

	@Extension
	public static final class DescriptorImpl extends ViewDescriptor {

		@Override
		public String getDisplayName() {
			return "Sectioned View";
		}
	}

	@Override
	public boolean contains(TopLevelItem item) {
		for (SectionedViewSection section : sections) {
			if (section.contains(item)) {
				return true;
			}
		}
		return false;
	}

	@Override
	public Item doCreateItem(StaplerRequest req, StaplerResponse rsp)
			throws IOException, ServletException {
        return Hudson.getInstance().doCreateItem(req, rsp);
	}

	@Override
	public Collection<TopLevelItem> getItems() {
		SortedSet<String> names = new TreeSet<String>();

		for (SectionedViewSection section : sections) {
			names.addAll(section.jobNames);
		}

		List<TopLevelItem> items = new ArrayList<TopLevelItem>(names.size());
		for (String n : names) {
			TopLevelItem item = Hudson.getInstance().getItem(n);
			if (item != null)
				items.add(item);
		}
		return items;
	}

	@Override
	public void onJobRenamed(Item item, String oldName, String newName) {
		for (SectionedViewSection section : sections) {
	        if(section.jobNames.remove(oldName) && newName!=null)
	        	section.jobNames.add(newName);
		}
	}
}

@@ -3892,99 +3892,8 @@
 ();%0A
-%0A%09%09for (SectionedViewSection section : sections) %7B%0A%09%09%09names.addAll(section.jobNames);%0A%09%09%7D%0A%0A
 %09%09Li
@@ -3960,24 +3960,25 @@
 ize());%0A
+%0A
 %09%09for (S
 tring n 
@@ -3973,129 +3973,95 @@
 r (S
-tring n : names) %7B%0A%09%09%09TopLevelItem item = Hudson.getInstance().getItem(n);%0A%09%09%09if (item != null)%0A%09%09%09%09items.add(item
+ectionedViewSection section : sections) %7B%0A%09%09    items.addAll(section.getItems()
 );%0A%09%09%7D%0A
+%0A
 %09%09re

correct implementation of getItems so this works with the new filterBuild/filterQueue functionality