/*
 * 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>();
		Map<Integer, Integer> latestRevisions = new HashMap<Integer, Integer>();
		
		int latestPatchsetNumber = -1;
		
		List<Integer> deletedPatchsets = new ArrayList<Integer>();
		
		for (Change change : changes) {
			if (change.patchset != null) {
				if (change.patchset.isDeleted()) {
					deletedPatchsets.add(change.patchset.number);
				} else {
					Integer latestRev = latestRevisions.get(change.patchset.number);
					
					if (latestRev == null || change.patchset.rev > latestRev) {
						latestRevisions.put(change.patchset.number, change.patchset.rev);
					}
					
					if (change.patchset.number > latestPatchsetNumber) {
						latestPatchsetNumber = change.patchset.number;
					}	
				}
			}
		}
		
		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 if (change.patchset != null) {
				//All revisions of a deleted patchset are not displayed
				if (!deletedPatchsets.contains(change.patchset.number)) {
					
					Integer latestRev = latestRevisions.get(change.patchset.number);
					
					if (    (change.patchset.number < latestPatchsetNumber) 
						 && (change.patchset.rev == latestRev)) {
						change.patchset.canDelete = true;
					}
					
					effectiveChanges.add(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 transient boolean canDelete = false;

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

		public boolean isDeleted() {
			return PatchsetType.Delete == 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, Delete;

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