/*******************************************************************************
 * Copyright (c) 2013 Ericsson
 * 
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *   Francois Chouinard - Initial implementation
 ******************************************************************************/

package org.eclipse.mylyn.gerrit.dashboard.core;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.eclipse.mylyn.internal.gerrit.core.GerritQueryResultSchema;
import org.eclipse.mylyn.internal.gerrit.core.GerritTaskSchema;
import org.eclipse.mylyn.internal.tasks.core.AbstractTask;
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
import org.eclipse.mylyn.tasks.core.data.TaskData;

/**
 * A Dashboard Gerrit review task
 * 
 * @author Francois Chouinard
 * @version 0.1
 */
@SuppressWarnings("restriction")
public class GerritTask extends AbstractTask {

	// -------------------------------------------------------------------------
	// Constants
	// -------------------------------------------------------------------------

	/**
	 * Mylyn Task ID
	 */
	public static final String TASK_ID = "dashboard.mylyn.task.id";

	/**
	 * Gerrit Review shortened Change-Id
	 */
	public static final String SHORT_CHANGE_ID = TaskAttribute.TASK_KEY;

	/**
	 * Gerrit Review Change-Id
	 */
	public static final String CHANGE_ID = GerritQueryResultSchema.getDefault().CHANGE_ID
			.getKey();

	/**
	 * Gerrit Review subject
	 */
	public static final String SUBJECT = TaskAttribute.SUMMARY;

	/**
	 * Gerrit Review owner
	 */
	public static final String OWNER = GerritTaskSchema.getDefault().OWNER
			.getKey();

	/**
	 * Gerrit Review project
	 */
	public static final String PROJECT = TaskAttribute.PRODUCT;

	/**
	 * Gerrit Review branch
	 */
	public static final String BRANCH = GerritTaskSchema.getDefault().BRANCH
			.getKey();

	/**
	 * Gerrit Review creation date
	 */
	public static final String DATE_CREATION = TaskAttribute.DATE_CREATION;

	/**
	 * Gerrit Review last modification date
	 */
	public static final String DATE_MODIFICATION = TaskAttribute.DATE_MODIFICATION;

	/**
	 * Gerrit Review completion date
	 */
	public static final String DATE_COMPLETION = TaskAttribute.DATE_COMPLETION;

	/**
	 * Gerrit Review flags
	 */
	public static final String IS_STARRED = GerritTaskSchema.getDefault().IS_STARRED
			.getKey();
	public static final String REVIEW_STATE = GerritTaskSchema.getDefault().REVIEW_STATE
			.getKey();
	public static final String VERIFY_STATE = GerritTaskSchema.getDefault().VERIFY_STATE
			.getKey();

	/**
	 * Date format
	 */
	private static SimpleDateFormat FORMAT_HOUR = new SimpleDateFormat("h:mm a");
	private static SimpleDateFormat FORMAT_MONTH = new SimpleDateFormat("MMM d");
	private static SimpleDateFormat FORMAT_FULL = new SimpleDateFormat(
			"MMM d, yyyy");

	// -------------------------------------------------------------------------
	// Attributes
	// -------------------------------------------------------------------------

	// The connector kind
	private final String fConnectorKind;

	// -------------------------------------------------------------------------
	// Constructor
	// -------------------------------------------------------------------------

	/**
	 * Construct an GerritTask from a Gerrit query result. Some fields may be
	 * missing from the task data.
	 * 
	 * @param taskData
	 *            the Gerrit task data
	 */
	public GerritTask(final TaskData taskData) {
		super(taskData.getRepositoryUrl(), taskData.getTaskId(), taskData
				.getRoot().getAttribute(TaskAttribute.SUMMARY).getValue()
				+ " ["
				+ taskData.getRoot().getAttribute(TaskAttribute.TASK_KEY)
						.getValue() + "]");

		fConnectorKind = taskData.getConnectorKind();

		TaskAttribute root = taskData.getRoot();
		Map<String, TaskAttribute> attributes = root.getAttributes();

		setAttribute(TASK_ID, taskData.getTaskId());
		setAttribute(SHORT_CHANGE_ID, getValue(attributes.get(SHORT_CHANGE_ID)));
		setAttribute(CHANGE_ID, getValue(attributes.get(CHANGE_ID)));
		setAttribute(SUBJECT, getValue(attributes.get(SUBJECT)));

		setAttribute(OWNER, getValue(attributes.get(OWNER)));
		setAttribute(PROJECT, getValue(attributes.get(PROJECT)));
		setAttribute(BRANCH, getValue(attributes.get(BRANCH)));

		setAttribute(DATE_CREATION, getValue(attributes.get(DATE_CREATION)));
		setAttribute(DATE_MODIFICATION,
				getValue(attributes.get(DATE_MODIFICATION)));
		setAttribute(DATE_COMPLETION, getValue(attributes.get(DATE_COMPLETION)));

		setAttribute(IS_STARRED, getValue(attributes.get(IS_STARRED)));
		setAttribute(REVIEW_STATE, getValue(attributes.get(REVIEW_STATE)));
		setAttribute(VERIFY_STATE, getValue(attributes.get(VERIFY_STATE)));
	}

	/*
	 * Extract the first value from the specified task attributes list.
	 * 
	 * @param taskAttribute
	 * 
	 * @return the first value in the list (if any)
	 */
	private String getValue(TaskAttribute taskAttribute) {
		if (taskAttribute != null) {
			List<String> values = taskAttribute.getValues();
			if (values != null && values.size() > 0) {
				return values.get(0);
			}
		}
		return null;
	}

	// -------------------------------------------------------------------------
	// Getters and Setters
	// -------------------------------------------------------------------------

	/**
	 * Format the requested Gerrit Review attribute as a date string. As in the
	 * Gerrit web UI, the output format depends on the date relation with
	 * 'today':
	 * 
	 * Same day: 'hh:mm am/pm' Same year, different day: 'Mon DD' Different
	 * year: 'Mon DD, YYYY' (not implemented)
	 * 
	 * @param key
	 *            one of { DATE_CREATION, DATE_MODIFICATION, DATE_COMPLETION }
	 * 
	 * @return
	 */
	public String getAttributeAsDate(String key) {
		// Validate the supplied key
		if (!key.equals(DATE_CREATION) && !key.equals(DATE_MODIFICATION)
				&& !key.equals(DATE_COMPLETION)) {
			return "";
		}

		// Retrieve the date
		String rawDate = getAttribute(key);
		if (rawDate == null) {
			return "";
		}

		// Format the date
		Date date = new Date(Long.parseLong(rawDate));
		if (isToday(date)) {
			return FORMAT_HOUR.format(date);
		}
		if (isThisYear(date)) {
			return FORMAT_MONTH.format(date);
		}
		return FORMAT_FULL.format(date);
	}

	/**
	 * Indicates if a date is 'today'
	 * 
	 * @param date
	 *            the date to check against 'today'
	 * @return true if 'today'
	 */
	private boolean isToday(Date date) {
		Calendar cal1 = Calendar.getInstance(); // today
		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(date);

		boolean sameDay = (cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && (cal1
				.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR)));

		return sameDay;
	}

	/**
	 * Indicates if a date is 'this year'
	 * 
	 * @param date
	 *            the date to check
	 * @return true if same year as today
	 */
	private boolean isThisYear(Date date) {
		Calendar cal1 = Calendar.getInstance(); // today
		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(date);

		return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);
	}

	// -------------------------------------------------------------------------
	// AbstractTask
	// -------------------------------------------------------------------------

	@Override
	public boolean isLocal() {
		return false;
	}

	@Override
	public String getConnectorKind() {
		return fConnectorKind;
	}

	// -------------------------------------------------------------------------
	// Object
	// -------------------------------------------------------------------------

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("TaskID  = ").append(getAttribute(GerritTask.TASK_ID))
				.append("\n");
		buffer.append("ShortID = ")
				.append(getAttribute(GerritTask.SHORT_CHANGE_ID)).append("\n");
		buffer.append("ChangeID= ").append(getAttribute(GerritTask.CHANGE_ID))
				.append("\n");
		buffer.append("Subject = ").append(getAttribute(GerritTask.SUBJECT))
				.append("\n");
		buffer.append("Owner   = ").append(getAttribute(GerritTask.OWNER))
				.append("\n");
		buffer.append("Project = ").append(getAttribute(GerritTask.PROJECT))
				.append("\n");
		buffer.append("Branch  = ").append(getAttribute(GerritTask.BRANCH))
				.append("\n");
		buffer.append("Updated = ")
				.append(getAttributeAsDate(GerritTask.DATE_MODIFICATION))
				.append("\n");
		buffer.append("STAR = ").append(getAttribute(GerritTask.IS_STARRED))
				.append(", CRVW = ")
				.append(getAttribute(GerritTask.REVIEW_STATE))
				.append(", VRIF = ")
				.append(getAttribute(GerritTask.VERIFY_STATE)).append("\n");
		return buffer.toString();
	}

}
