/*
 * 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;

	/**
	 * 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;
	}

	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;
				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();
		}

		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;
	}

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

		public static Type defaultType = Task;

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

		@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;

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

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

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

		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;
		}
	}
}
