/*
 * Copyright 2014 gitblit.com.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitblit.models;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.jgit.util.RelativeDateFormatter;

/**
 * The Gitblit Ticket model, its component classes, and enums.
 *
 * @author James Moger
 *
 */
public class TicketModel implements Serializable, Comparable<TicketModel> {

	private static final long serialVersionUID = 1L;

	public String project;

	public String repository;

	public long number;

	public Date created;

	public String createdBy;

	public Date updated;

	public String updatedBy;

	public String title;

	public String body;

	public String topic;

	public Type type;

	public Status status;

	public String responsible;

	public String milestone;

	public String mergeSha;

	public String mergeTo;

	public List<Change> changes;

	public Integer insertions;

	public Integer deletions;

	public Priority priority;
	
	public Severity severity;
	
	/**
	 * Builds an effective ticket from the collection of changes.  A change may
	 * Add or Subtract information from a ticket, but the collection of changes
	 * is only additive.
	 *
	 * @param changes
	 * @return the effective ticket
	 */
	public static TicketModel buildTicket(Collection<Change> changes) {
		TicketModel ticket;
		List<Change> effectiveChanges = new ArrayList<Change>();
		Map<String, Change> comments = new HashMap<String, Change>();
		for (Change change : changes) {
			if (change.comment != null) {
				if (comments.containsKey(change.comment.id)) {
					Change original = comments.get(change.comment.id);
					Change clone = copy(original);
					clone.comment.text = change.comment.text;
					clone.comment.deleted = change.comment.deleted;
					int idx = effectiveChanges.indexOf(original);
					effectiveChanges.remove(original);
					effectiveChanges.add(idx, clone);
					comments.put(clone.comment.id, clone);
				} else {
					effectiveChanges.add(change);
					comments.put(change.comment.id, change);
				}
			} else {
				effectiveChanges.add(change);
			}
		}

		// effective ticket
		ticket = new TicketModel();
		for (Change change : effectiveChanges) {
			if (!change.hasComment()) {
				// ensure we do not include a deleted comment
				change.comment = null;
			}
			ticket.applyChange(change);
		}
		return ticket;
	}

	public TicketModel() {
		// the first applied change set the date appropriately
		created = new Date(0);
		changes = new ArrayList<Change>();
		status = Status.New;
		type = Type.defaultType;
		priority = Priority.defaultPriority;
		severity = Severity.defaultSeverity;
	}

	public boolean isOpen() {
		return !status.isClosed();
	}

	public boolean isClosed() {
		return status.isClosed();
	}

	public boolean isMerged() {
		return isClosed() && !isEmpty(mergeSha);
	}

	public boolean isProposal() {
		return Type.Proposal == type;
	}

	public boolean isBug() {
		return Type.Bug == type;
	}

	public Date getLastUpdated() {
		return updated == null ? created : updated;
	}

	public boolean hasPatchsets() {
		return getPatchsets().size() > 0;
	}

	/**
	 * Returns true if multiple participants are involved in discussing a ticket.
	 * The ticket creator is excluded from this determination because a
	 * discussion requires more than one participant.
	 *
	 * @return true if this ticket has a discussion
	 */
	public boolean hasDiscussion() {
		for (Change change : getComments()) {
			if (!change.author.equals(createdBy)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Returns the list of changes with comments.
	 *
	 * @return
	 */
	public List<Change> getComments() {
		List<Change> list = new ArrayList<Change>();
		for (Change change : changes) {
			if (change.hasComment()) {
				list.add(change);
			}
		}
		return list;
	}

	/**
	 * Returns the list of participants for the ticket.
	 *
	 * @return the list of participants
	 */
	public List<String> getParticipants() {
		Set<String> set = new LinkedHashSet<String>();
		for (Change change : changes) {
			if (change.isParticipantChange()) {
				set.add(change.author);
			}
		}
		if (responsible != null && responsible.length() > 0) {
			set.add(responsible);
		}
		return new ArrayList<String>(set);
	}

	public boolean hasLabel(String label) {
		return getLabels().contains(label);
	}

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

	public boolean isResponsible(String username) {
		return username.equals(responsible);
	}

	public boolean isAuthor(String username) {
		return username.equals(createdBy);
	}

	public boolean isReviewer(String username) {
		return getReviewers().contains(username);
	}

	public List<String> getReviewers() {
		return getList(Field.reviewers);
	}

	public boolean isWatching(String username) {
		return getWatchers().contains(username);
	}

	public List<String> getWatchers() {
		return getList(Field.watchers);
	}

	public boolean isVoter(String username) {
		return getVoters().contains(username);
	}

	public List<String> getVoters() {
		return getList(Field.voters);
	}

	public List<String> getMentions() {
		return getList(Field.mentions);
	}

	protected List<String> getList(Field field) {
		Set<String> set = new TreeSet<String>();
		for (Change change : changes) {
			if (change.hasField(field)) {
				String values = change.getString(field);
				for (String value : values.split(",")) {
					switch (value.charAt(0)) {
					case '+':
						set.add(value.substring(1));
						break;
					case '-':
						set.remove(value.substring(1));
						break;
					default:
						set.add(value);
					}
				}
			}
		}
		if (!set.isEmpty()) {
			return new ArrayList<String>(set);
		}
		return Collections.emptyList();
	}

	public Attachment getAttachment(String name) {
		Attachment attachment = null;
		for (Change change : changes) {
			if (change.hasAttachments()) {
				Attachment a = change.getAttachment(name);
				if (a != null) {
					attachment = a;
				}
			}
		}
		return attachment;
	}

	public boolean hasAttachments() {
		for (Change change : changes) {
			if (change.hasAttachments()) {
				return true;
			}
		}
		return false;
	}

	public List<Attachment> getAttachments() {
		List<Attachment> list = new ArrayList<Attachment>();
		for (Change change : changes) {
			if (change.hasAttachments()) {
				list.addAll(change.attachments);
			}
		}
		return list;
	}

	public List<Patchset> getPatchsets() {
		List<Patchset> list = new ArrayList<Patchset>();
		for (Change change : changes) {
			if (change.patchset != null) {
				list.add(change.patchset);
			}
		}
		return list;
	}

	public List<Patchset> getPatchsetRevisions(int number) {
		List<Patchset> list = new ArrayList<Patchset>();
		for (Change change : changes) {
			if (change.patchset != null) {
				if (number == change.patchset.number) {
					list.add(change.patchset);
				}
			}
		}
		return list;
	}

	public Patchset getPatchset(String sha) {
		for (Change change : changes) {
			if (change.patchset != null) {
				if (sha.equals(change.patchset.tip)) {
					return change.patchset;
				}
			}
		}
		return null;
	}

	public Patchset getPatchset(int number, int rev) {
		for (Change change : changes) {
			if (change.patchset != null) {
				if (number == change.patchset.number && rev == change.patchset.rev) {
					return change.patchset;
				}
			}
		}
		return null;
	}

	public Patchset getCurrentPatchset() {
		Patchset patchset = null;
		for (Change change : changes) {
			if (change.patchset != null) {
				if (patchset == null) {
					patchset = change.patchset;
				} else if (patchset.compareTo(change.patchset) == 1) {
					patchset = change.patchset;
				}
			}
		}
		return patchset;
	}

	public boolean isCurrent(Patchset patchset) {
		if (patchset == null) {
			return false;
		}
		Patchset curr = getCurrentPatchset();
		if (curr == null) {
			return false;
		}
		return curr.equals(patchset);
	}

	public List<Change> getReviews(Patchset patchset) {
		if (patchset == null) {
			return Collections.emptyList();
		}
		// collect the patchset reviews by author
		// the last review by the author is the
		// official review
		Map<String, Change> reviews = new LinkedHashMap<String, TicketModel.Change>();
		for (Change change : changes) {
			if (change.hasReview()) {
				if (change.review.isReviewOf(patchset)) {
					reviews.put(change.author, change);
				}
			}
		}
		return new ArrayList<Change>(reviews.values());
	}


	public boolean isApproved(Patchset patchset) {
		if (patchset == null) {
			return false;
		}
		boolean approved = false;
		boolean vetoed = false;
		for (Change change : getReviews(patchset)) {
			if (change.hasReview()) {
				if (change.review.isReviewOf(patchset)) {
					if (Score.approved == change.review.score) {
						approved = true;
					} else if (Score.vetoed == change.review.score) {
						vetoed = true;
					}
				}
			}
		}
		return approved && !vetoed;
	}

	public boolean isVetoed(Patchset patchset) {
		if (patchset == null) {
			return false;
		}
		for (Change change : getReviews(patchset)) {
			if (change.hasReview()) {
				if (change.review.isReviewOf(patchset)) {
					if (Score.vetoed == change.review.score) {
						return true;
					}
				}
			}
		}
		return false;
	}

	public Review getReviewBy(String username) {
		for (Change change : getReviews(getCurrentPatchset())) {
			if (change.author.equals(username)) {
				return change.review;
			}
		}
		return null;
	}

	public boolean isPatchsetAuthor(String username) {
		for (Change change : changes) {
			if (change.hasPatchset()) {
				if (change.author.equals(username)) {
					return true;
				}
			}
		}
		return false;
	}

	public void applyChange(Change change) {
		if (changes.size() == 0) {
			// first change created the ticket
			created = change.date;
			createdBy = change.author;
			status = Status.New;
		} else if (created == null || change.date.after(created)) {
			// track last ticket update
			updated = change.date;
			updatedBy = change.author;
		}

		if (change.isMerge()) {
			// identify merge patchsets
			if (isEmpty(responsible)) {
				responsible = change.author;
			}
			status = Status.Merged;
		}

		if (change.hasFieldChanges()) {
			for (Map.Entry<Field, String> entry : change.fields.entrySet()) {
				Field field = entry.getKey();
				Object value = entry.getValue();
				switch (field) {
				case type:
					type = TicketModel.Type.fromObject(value, type);
					break;
				case status:
					status = TicketModel.Status.fromObject(value, status);
					break;
				case title:
					title = toString(value);
					break;
				case body:
					body = toString(value);
					break;
				case topic:
					topic = toString(value);
					break;
				case responsible:
					responsible = toString(value);
					break;
				case milestone:
					milestone = toString(value);
					break;
				case mergeTo:
					mergeTo = toString(value);
					break;
				case mergeSha:
					mergeSha = toString(value);
					break;
				case priority:
					priority = TicketModel.Priority.fromObject(value, priority);
					break;
				case severity:
					severity = TicketModel.Severity.fromObject(value, severity);
					break;
				default:
					// unknown
					break;
				}
			}
		}

		// add the change to the ticket
		changes.add(change);
	}

	protected String toString(Object value) {
		if (value == null) {
			return null;
		}
		return value.toString();
	}

	public String toIndexableString() {
		StringBuilder sb = new StringBuilder();
		if (!isEmpty(title)) {
			sb.append(title).append('\n');
		}
		if (!isEmpty(body)) {
			sb.append(body).append('\n');
		}
		for (Change change : changes) {
			if (change.hasComment()) {
				sb.append(change.comment.text);
				sb.append('\n');
			}
		}
		return sb.toString();
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("#");
		sb.append(number);
		sb.append(": " + title + "\n");
		for (Change change : changes) {
			sb.append(change);
			sb.append('\n');
		}
		return sb.toString();
	}

	@Override
	public int compareTo(TicketModel o) {
		return o.created.compareTo(created);
	}

	@Override
	public boolean equals(Object o) {
		if (o instanceof TicketModel) {
			return number == ((TicketModel) o).number;
		}
		return super.equals(o);
	}

	@Override
	public int hashCode() {
		return (repository + number).hashCode();
	}

	/**
	 * Encapsulates a ticket change
	 */
	public static class Change implements Serializable, Comparable<Change> {

		private static final long serialVersionUID = 1L;

		public final Date date;

		public final String author;

		public Comment comment;

		public Map<Field, String> fields;

		public Set<Attachment> attachments;

		public Patchset patchset;

		public Review review;

		private transient String id;

		public Change(String author) {
			this(author, new Date());
		}

		public Change(String author, Date date) {
			this.date = date;
			this.author = author;
		}

		public boolean isStatusChange() {
			return hasField(Field.status);
		}

		public Status getStatus() {
			Status state = Status.fromObject(getField(Field.status), null);
			return state;
		}

		public boolean isMerge() {
			return hasField(Field.status) && hasField(Field.mergeSha);
		}

		public boolean hasPatchset() {
			return patchset != null;
		}

		public boolean hasReview() {
			return review != null;
		}

		public boolean hasComment() {
			return comment != null && !comment.isDeleted() && comment.text != null;
		}

		public Comment comment(String text) {
			comment = new Comment(text);
			comment.id = TicketModel.getSHA1(date.toString() + author + text);

			try {
				Pattern mentions = Pattern.compile("\\s@([A-Za-z0-9-_]+)");
				Matcher m = mentions.matcher(text);
				while (m.find()) {
					String username = m.group(1);
					plusList(Field.mentions, username);
				}
			} catch (Exception e) {
				// ignore
			}
			return comment;
		}

		public Review review(Patchset patchset, Score score, boolean addReviewer) {
			if (addReviewer) {
				plusList(Field.reviewers, author);
			}
			review = new Review(patchset.number, patchset.rev);
			review.score = score;
			return review;
		}

		public boolean hasAttachments() {
			return !TicketModel.isEmpty(attachments);
		}

		public void addAttachment(Attachment attachment) {
			if (attachments == null) {
				attachments = new LinkedHashSet<Attachment>();
			}
			attachments.add(attachment);
		}

		public Attachment getAttachment(String name) {
			if (attachments != null) {
				for (Attachment attachment : attachments) {
					if (attachment.name.equalsIgnoreCase(name)) {
						return attachment;
					}
				}
			}
			return null;
		}

		public boolean isParticipantChange() {
			if (hasComment()
					|| hasReview()
					|| hasPatchset()
					|| hasAttachments()) {
				return true;
			}

			if (TicketModel.isEmpty(fields)) {
				return false;
			}

			// identify real ticket field changes
			Map<Field, String> map = new HashMap<Field, String>(fields);
			map.remove(Field.watchers);
			map.remove(Field.voters);
			return !map.isEmpty();
		}

		public boolean hasField(Field field) {
			return !TicketModel.isEmpty(getString(field));
		}

		public boolean hasFieldChanges() {
			return !TicketModel.isEmpty(fields);
		}

		public String getField(Field field) {
			if (fields != null) {
				return fields.get(field);
			}
			return null;
		}

		public void setField(Field field, Object value) {
			if (fields == null) {
				fields = new LinkedHashMap<Field, String>();
			}
			if (value == null) {
				fields.put(field, null);
			} else if (Enum.class.isAssignableFrom(value.getClass())) {
				fields.put(field, ((Enum<?>) value).name());
			} else {
				fields.put(field, value.toString());
			}
		}

		public void remove(Field field) {
			if (fields != null) {
				fields.remove(field);
			}
		}

		public String getString(Field field) {
			String value = getField(field);
			if (value == null) {
				return null;
			}
			return value;
		}

		public void watch(String... username) {
			plusList(Field.watchers, username);
		}

		public void unwatch(String... username) {
			minusList(Field.watchers, username);
		}

		public void vote(String... username) {
			plusList(Field.voters, username);
		}

		public void unvote(String... username) {
			minusList(Field.voters, username);
		}

		public void label(String... label) {
			plusList(Field.labels, label);
		}

		public void unlabel(String... label) {
			minusList(Field.labels, label);
		}

		protected void plusList(Field field, String... items) {
			modList(field, "+", items);
		}

		protected void minusList(Field field, String... items) {
			modList(field, "-", items);
		}

		private void modList(Field field, String prefix, String... items) {
			List<String> list = new ArrayList<String>();
			for (String item : items) {
				list.add(prefix + item);
			}
			if (hasField(field)) {
				String flat = getString(field);
				if (isEmpty(flat)) {
					// field is empty, use this list
					setField(field, join(list, ","));
				} else {
					// merge this list into the existing field list
					Set<String> set = new TreeSet<String>(Arrays.asList(flat.split(",")));
					set.addAll(list);
					setField(field, join(set, ","));
				}
			} else {
				// does not have a list for this field
				setField(field, join(list, ","));
			}
		}

		public String getId() {
			if (id == null) {
				id = getSHA1(Long.toHexString(date.getTime()) + author);
			}
			return id;
		}

		@Override
		public int compareTo(Change c) {
			return date.compareTo(c.date);
		}

		@Override
		public int hashCode() {
			return getId().hashCode();
		}

		@Override
		public boolean equals(Object o) {
			if (o instanceof Change) {
				return getId().equals(((Change) o).getId());
			}
			return false;
		}

		@Override
		public String toString() {
			StringBuilder sb = new StringBuilder();
			sb.append(RelativeDateFormatter.format(date));
			if (hasComment()) {
				sb.append(" commented on by ");
			} else if (hasPatchset()) {
				sb.append(MessageFormat.format(" {0} uploaded by ", patchset));
			} else {
				sb.append(" changed by ");
			}
			sb.append(author).append(" - ");
			if (hasComment()) {
				if (comment.isDeleted()) {
					sb.append("(deleted) ");
				}
				sb.append(comment.text).append(" ");
			}

			if (hasFieldChanges()) {
				for (Map.Entry<Field, String> entry : fields.entrySet()) {
					sb.append("\n  ");
					sb.append(entry.getKey().name());
					sb.append(':');
					sb.append(entry.getValue());
				}
			}
			return sb.toString();
		}
	}

	/**
	 * Returns true if the string is null or empty.
	 *
	 * @param value
	 * @return true if string is null or empty
	 */
	static boolean isEmpty(String value) {
		return value == null || value.trim().length() == 0;
	}

	/**
	 * Returns true if the collection is null or empty
	 *
	 * @param collection
	 * @return
	 */
	static boolean isEmpty(Collection<?> collection) {
		return collection == null || collection.size() == 0;
	}

	/**
	 * Returns true if the map is null or empty
	 *
	 * @param map
	 * @return
	 */
	static boolean isEmpty(Map<?, ?> map) {
		return map == null || map.size() == 0;
	}

	/**
	 * Calculates the SHA1 of the string.
	 *
	 * @param text
	 * @return sha1 of the string
	 */
	static String getSHA1(String text) {
		try {
			byte[] bytes = text.getBytes("iso-8859-1");
			return getSHA1(bytes);
		} catch (UnsupportedEncodingException u) {
			throw new RuntimeException(u);
		}
	}

	/**
	 * Calculates the SHA1 of the byte array.
	 *
	 * @param bytes
	 * @return sha1 of the byte array
	 */
	static String getSHA1(byte[] bytes) {
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			md.update(bytes, 0, bytes.length);
			byte[] digest = md.digest();
			return toHex(digest);
		} catch (NoSuchAlgorithmException t) {
			throw new RuntimeException(t);
		}
	}

	/**
	 * Returns the hex representation of the byte array.
	 *
	 * @param bytes
	 * @return byte array as hex string
	 */
	static String toHex(byte[] bytes) {
		StringBuilder sb = new StringBuilder(bytes.length * 2);
		for (int i = 0; i < bytes.length; i++) {
			if ((bytes[i] & 0xff) < 0x10) {
				sb.append('0');
			}
			sb.append(Long.toString(bytes[i] & 0xff, 16));
		}
		return sb.toString();
	}

	/**
	 * Join the list of strings into a single string with a space separator.
	 *
	 * @param values
	 * @return joined list
	 */
	static String join(Collection<String> values) {
		return join(values, " ");
	}

	/**
	 * Join the list of strings into a single string with the specified
	 * separator.
	 *
	 * @param values
	 * @param separator
	 * @return joined list
	 */
	static String join(String[]  values, String separator) {
		return join(Arrays.asList(values), separator);
	}

	/**
	 * Join the list of strings into a single string with the specified
	 * separator.
	 *
	 * @param values
	 * @param separator
	 * @return joined list
	 */
	static String join(Collection<String> values, String separator) {
		StringBuilder sb = new StringBuilder();
		for (String value : values) {
			sb.append(value).append(separator);
		}
		if (sb.length() > 0) {
			// truncate trailing separator
			sb.setLength(sb.length() - separator.length());
		}
		return sb.toString().trim();
	}


	/**
	 * Produce a deep copy of the given object. Serializes the entire object to
	 * a byte array in memory. Recommended for relatively small objects.
	 */
	@SuppressWarnings("unchecked")
	static <T> T copy(T original) {
		T o = null;
		try {
			ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(byteOut);
			oos.writeObject(original);
			ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
			ObjectInputStream ois = new ObjectInputStream(byteIn);
			try {
				o = (T) ois.readObject();
			} catch (ClassNotFoundException cex) {
				// actually can not happen in this instance
			}
		} catch (IOException iox) {
			// doesn't seem likely to happen as these streams are in memory
			throw new RuntimeException(iox);
		}
		return o;
	}

	public static class Patchset implements Serializable, Comparable<Patchset> {

		private static final long serialVersionUID = 1L;

		public int number;
		public int rev;
		public String tip;
		public String parent;
		public String base;
		public int insertions;
		public int deletions;
		public int commits;
		public int added;
		public PatchsetType type;

		public boolean isFF() {
			return PatchsetType.FastForward == type;
		}

		@Override
		public int hashCode() {
			return toString().hashCode();
		}

		@Override
		public boolean equals(Object o) {
			if (o instanceof Patchset) {
				return hashCode() == o.hashCode();
			}
			return false;
		}

		@Override
		public int compareTo(Patchset p) {
			if (number > p.number) {
				return -1;
			} else if (p.number > number) {
				return 1;
			} else {
				// same patchset, different revision
				if (rev > p.rev) {
					return -1;
				} else if (p.rev > rev) {
					return 1;
				} else {
					// same patchset & revision
					return 0;
				}
			}
		}

		@Override
		public String toString() {
			return "patchset " + number + " revision " + rev;
		}
	}

	public static class Comment implements Serializable {

		private static final long serialVersionUID = 1L;

		public String text;

		public String id;

		public Boolean deleted;

		public CommentSource src;

		public String replyTo;

		Comment(String text) {
			this.text = text;
		}

		public boolean isDeleted() {
			return deleted != null && deleted;
		}

		@Override
		public String toString() {
			return text;
		}
	}

	public static class Attachment implements Serializable {

		private static final long serialVersionUID = 1L;

		public final String name;
		public long size;
		public byte[] content;
		public Boolean deleted;

		public Attachment(String name) {
			this.name = name;
		}

		public boolean isDeleted() {
			return deleted != null && deleted;
		}

		@Override
		public int hashCode() {
			return name.hashCode();
		}

		@Override
		public boolean equals(Object o) {
			if (o instanceof Attachment) {
				return name.equalsIgnoreCase(((Attachment) o).name);
			}
			return false;
		}

		@Override
		public String toString() {
			return name;
		}
	}

	public static class Review implements Serializable {

		private static final long serialVersionUID = 1L;

		public final int patchset;

		public final int rev;

		public Score score;

		public Review(int patchset, int revision) {
			this.patchset = patchset;
			this.rev = revision;
		}

		public boolean isReviewOf(Patchset p) {
			return patchset == p.number && rev == p.rev;
		}

		@Override
		public String toString() {
			return "review of patchset " + patchset + " rev " + rev + ":" + score;
		}
	}

	public static enum Score {
		approved(2), looks_good(1), not_reviewed(0), needs_improvement(-1), vetoed(
				-2);

		final int value;

		Score(int value) {
			this.value = value;
		}

		public int getValue() {
			return value;
		}

		@Override
		public String toString() {
			return name().toLowerCase().replace('_', ' ');
		}

		public static Score fromScore(int score) {
			for (Score s : values()) {
				if (s.getValue() == score) {
					return s;
				}
			}
			throw new NoSuchElementException(String.valueOf(score));
		}
	}

	public static enum Field {
		title, body, responsible, type, status, milestone, mergeSha, mergeTo,
		topic, labels, watchers, reviewers, voters, mentions, priority, severity;
	}

	public static enum Type {
		Enhancement, Task, Bug, Proposal, Question, Maintenance;

		public static Type defaultType = Task;

		public static Type [] choices() {
			return new Type [] { Enhancement, Task, Bug, Question, Maintenance };
		}

		@Override
		public String toString() {
			return name().toLowerCase().replace('_', ' ');
		}

		public static Type fromObject(Object o, Type defaultType) {
			if (o instanceof Type) {
				// cast and return
				return (Type) o;
			} else if (o instanceof String) {
				// find by name
				for (Type type : values()) {
					String str = o.toString();
					if (type.name().equalsIgnoreCase(str)
							|| type.toString().equalsIgnoreCase(str)) {
						return type;
					}
				}
			} else if (o instanceof Number) {
				// by ordinal
				int id = ((Number) o).intValue();
				if (id >= 0 && id < values().length) {
					return values()[id];
				}
			}

			return defaultType;
		}
	}

	public static enum Status {
		New, Open, Closed, Resolved, Fixed, Merged, Wontfix, Declined, Duplicate, Invalid, Abandoned, On_Hold, No_Change_Required;

		public static Status [] requestWorkflow = { Open, Resolved, Declined, Duplicate, Invalid, Abandoned, On_Hold, No_Change_Required };

		public static Status [] bugWorkflow = { Open, Fixed, Wontfix, Duplicate, Invalid, Abandoned, On_Hold, No_Change_Required };

		public static Status [] proposalWorkflow = { Open, Resolved, Declined, Abandoned, On_Hold, No_Change_Required };

		public static Status [] milestoneWorkflow = { Open, Closed, Abandoned, On_Hold };

		@Override
		public String toString() {
			return name().toLowerCase().replace('_', ' ');
		}

		public static Status fromObject(Object o, Status defaultStatus) {
			if (o instanceof Status) {
				// cast and return
				return (Status) o;
			} else if (o instanceof String) {
				// find by name
				String name = o.toString();
				for (Status state : values()) {
					if (state.name().equalsIgnoreCase(name)
							|| state.toString().equalsIgnoreCase(name)) {
						return state;
					}
				}
			} else if (o instanceof Number) {
				// by ordinal
				int id = ((Number) o).intValue();
				if (id >= 0 && id < values().length) {
					return values()[id];
				}
			}

			return defaultStatus;
		}

		public boolean isClosed() {
			return ordinal() > Open.ordinal();
		}
	}

	public static enum CommentSource {
		Comment, Email
	}

	public static enum PatchsetType {
		Proposal, FastForward, Rebase, Squash, Rebase_Squash, Amend;

		public boolean isRewrite() {
			return (this != FastForward) && (this != Proposal);
		}

		@Override
		public String toString() {
			return name().toLowerCase().replace('_', '+');
		}

		public static PatchsetType fromObject(Object o) {
			if (o instanceof PatchsetType) {
				// cast and return
				return (PatchsetType) o;
			} else if (o instanceof String) {
				// find by name
				String name = o.toString();
				for (PatchsetType type : values()) {
					if (type.name().equalsIgnoreCase(name)
							|| type.toString().equalsIgnoreCase(name)) {
						return type;
					}
				}
			} else if (o instanceof Number) {
				// by ordinal
				int id = ((Number) o).intValue();
				if (id >= 0 && id < values().length) {
					return values()[id];
				}
			}

			return null;
		}
	}

	public static enum Priority {
		Low(-1), Normal(0), High(1), Urgent(2);

		public static Priority defaultPriority = Normal;

		final int value;

		Priority(int value) {
			this.value = value;
		}

		public int getValue() {
			return value;
		}
		
		public static Priority [] choices() {
			return new Priority [] { Urgent, High, Normal, Low };
		}

		@Override
		public String toString() {
			return name().toLowerCase().replace('_', ' ');
		}

		public static Priority fromObject(Object o, Priority defaultPriority) {
			if (o instanceof Priority) {
				// cast and return
				return (Priority) o;
			} else if (o instanceof String) {
				// find by name
				for (Priority priority : values()) {
					String str = o.toString();
					if (priority.name().equalsIgnoreCase(str)
							|| priority.toString().equalsIgnoreCase(str)) {
						return priority;
					}
				}
			} else if (o instanceof Number) {

				switch (((Number) o).intValue()) {
					case -1: return Priority.Low;
					case 0:  return Priority.Normal;
					case 1:  return Priority.High;
					case 2:  return Priority.Urgent;
					default: return Priority.Normal;
				}
			}

			return defaultPriority;
		}
	}
	
	public static enum Severity {
		Unrated(-1), Negligible(1), Minor(2), Serious(3), Critical(4), Catastrophic(5);

		public static Severity defaultSeverity = Unrated;
		
		final int value;
		
		Severity(int value) {
			this.value = value;
		}

		public int getValue() {
			return value;
		}
		
		public static Severity [] choices() {
			return new Severity [] { Unrated, Negligible, Minor, Serious, Critical, Catastrophic };
		}

		@Override
		public String toString() {
			return name().toLowerCase().replace('_', ' ');
		}
		
		public static Severity fromObject(Object o, Severity defaultSeverity) {
			if (o instanceof Severity) {
				// cast and return
				return (Severity) o;
			} else if (o instanceof String) {
				// find by name
				for (Severity severity : values()) {
					String str = o.toString();
					if (severity.name().equalsIgnoreCase(str)
							|| severity.toString().equalsIgnoreCase(str)) {
						return severity;
					}
				}
			} else if (o instanceof Number) {
				
				switch (((Number) o).intValue()) {
					case -1: return Severity.Unrated;
					case 1:  return Severity.Negligible;
					case 2:  return Severity.Minor;
					case 3:  return Severity.Serious;
					case 4:  return Severity.Critical;
					case 5:  return Severity.Catastrophic;
					default: return Severity.Unrated;
				}
			}

			return defaultSeverity;
		}
	}
}
