/*******************************************************************************
 * Copyright (c) 2013, 2017 Frank Becker and others.
 * 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:
 *     Frank Becker - initial API and implementation
 *     Red Hat Inc. - modified for use with OpenShift.io
 *******************************************************************************/

package org.eclipse.linuxtools.internal.mylyn.osio.rest.core;

import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.linuxtools.internal.mylyn.osio.rest.core.response.data.Space;
import org.eclipse.linuxtools.internal.mylyn.osio.rest.core.response.data.User;
import org.eclipse.linuxtools.internal.mylyn.osio.rest.core.response.data.WorkItemTypeAttributes;
import org.eclipse.linuxtools.internal.mylyn.osio.rest.core.response.data.WorkItemTypeData;
import org.eclipse.linuxtools.internal.mylyn.osio.rest.core.response.data.WorkItemTypeField;
import org.eclipse.linuxtools.internal.mylyn.osio.rest.core.response.data.WorkItemTypeFieldType;
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
import org.eclipse.mylyn.tasks.core.data.TaskData;
import org.eclipse.mylyn.tasks.core.data.TaskOperation;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Ordering;

public class OSIORestConfiguration implements Serializable {

	private static final OSIORestTaskSchema SCHEMA = OSIORestTaskSchema.getDefault();

	private static final long serialVersionUID = 4173223872076958202L;

	private final String repositoryId;

	private Map<String, Space> spaces;
	
	private Map<String, User> users;
	
	private final static String NEW = "new"; //$NON-NLS-1$
	private final static String OPEN = "open"; //$NON-NLS-1$
	private final static String IN_PROGRESS = "in progress"; //$NON-NLS-1$
	private final static String RESOLVED = "resolved"; //$NON-NLS-1$
	private final static String CLOSED = "closed"; //$NON-NLS-1$
	
	private static final List<String> statusValues = Arrays.asList(new String[] {
			NEW, OPEN, IN_PROGRESS, RESOLVED, CLOSED});
	
	private static final List<String> newStatusTransitions = Arrays.asList(new String[] {
			OPEN, IN_PROGRESS, RESOLVED, CLOSED
	});
	private static final List<String> openStatusTransitions = Arrays.asList(new String[] {
			IN_PROGRESS, RESOLVED, CLOSED
	});
	private static final List<String> inProgressStatusTransitions = Arrays.asList(new String[] {
			OPEN, RESOLVED, CLOSED
	});
	private static final List<String> resolvedStatusTransitions = Arrays.asList(new String[] {
			OPEN, IN_PROGRESS, CLOSED
	});
	private static final List<String> closedStatusTransitions = Arrays.asList(new String[] {
			OPEN, IN_PROGRESS, RESOLVED
	});
	
	private Map<String, List<String>> statusTransitions = new HashMap<>();

	public OSIORestConfiguration(String repositoryId) {
		this.repositoryId = repositoryId;
		statusTransitions.put("", statusValues); //$NON-NLS-1$
		statusTransitions.put(NEW, newStatusTransitions);
		statusTransitions.put(OPEN, openStatusTransitions);
		statusTransitions.put(IN_PROGRESS, inProgressStatusTransitions);
		statusTransitions.put(RESOLVED, resolvedStatusTransitions);
		statusTransitions.put(CLOSED, closedStatusTransitions);
	}

	public String getRepositoryId() {
		return repositoryId;
	}


	public void setSpaces(Map<String, Space> spaces) {
		Function<Space, String> getName = new Function<Space, String>() {
			public String apply(Space item) {
				return item.getName();
			}
		};
		Function<String, String> comparatorFunction = Functions.compose(getName, Functions.forMap(spaces));
		Ordering<String> comparator = Ordering.natural().onResultOf(comparatorFunction);
		this.spaces = ImmutableSortedMap.copyOf(spaces, comparator);
	}

	public Map<String, Space> getSpaces() {
		return spaces;
	}

	public Space getSpaceWithName(String SpaceName) {
		return spaces.get(SpaceName);
	}

	public void updateInitialTaskData(TaskData data) throws CoreException {
		setSpaceOptions(data, getSpaces());
		updateSpaceOptions(data);
		for (String key : data.getRoot().getAttributes().keySet()) {
			if (key.equals(OSIORestTaskSchema.getDefault().NEW_COMMENT.getKey())
					|| key.equals(TaskAttribute.OPERATION)
					|| key.equals(OSIORestTaskSchema.getDefault().DATE_MODIFICATION.getKey())) {
				continue;
			}
			TaskAttribute attribute = data.getRoot().getAttribute(key);
			if (key.equals(OSIORestTaskSchema.getDefault().STATUS.getKey())) {
				if (attribute.getOptions().isEmpty()) {
					for (String status : statusValues) {
						attribute.putOption(status,  status);
					}
				}
			}
			if (!key.equals(SCHEMA.SPACE.getKey())) {
				String configName = mapTaskAttributeKey2ConfigurationFields(key);
				if (configName.equals("baseType")) {
					if (attribute.getOptions().size() == 1 && attribute.getValue().isEmpty()) {
						attribute.setValue((String) attribute.getOptions().values().toArray()[0]);
					}
				}
			}
		}
	}

	private String mapTaskAttributeKey2ConfigurationFields(String taskAttributeKey) {
		String resultString;
		if (taskAttributeKey.equals("task.common.summary")) {
			resultString = "system.title";
		} else if (taskAttributeKey.equals(TaskAttribute.STATUS)) {
			resultString = "system.state"; //$NON-NLS-1$
		} else if (taskAttributeKey.equals(TaskAttribute.USER_ASSIGNED)) {
			resultString = "assignees"; //$NON-NLS-1$
		} else if (taskAttributeKey.equals(TaskAttribute.DESCRIPTION)) {
			resultString = "system.description"; //$NON-NLS-1$
		} else if (taskAttributeKey.equals("comment")) { //$NON-NLS-1$
			resultString = "longdesc"; //$NON-NLS-1$
		} else {
			resultString = taskAttributeKey;
		}
		return resultString;
	}

	private void setAttributeOptionsForSpace(TaskAttribute taskAttribute, Space actualSpace) {
		taskAttribute.clearOptions();
		if (taskAttribute.getId().equals(SCHEMA.WORKITEM_TYPE.getKey())) {
			internalSetAttributeOptions(taskAttribute, actualSpace.getWorkItemTypes());
		} else if (taskAttribute.getId().equals(SCHEMA.AREA.getKey())) {
			internalSetAttributeOptions(taskAttribute, actualSpace.getAreas());
		} else if (taskAttribute.getId().equals(SCHEMA.ITERATION.getKey())) {
			internalSetAttributeOptions(taskAttribute, actualSpace.getIterations());
		} else if (taskAttribute.getId().equals(SCHEMA.ASSIGNEES.getKey())) {
			internalSetAttributeOptions(taskAttribute, actualSpace.getUsers());
		} else if (taskAttribute.getId().equals(SCHEMA.STATUS.getKey())) {
			Map<String, String> stateMap = new LinkedHashMap<>();
			Map<String, WorkItemTypeData> workItemTypes = actualSpace.getWorkItemTypes();
			for (Entry<String, WorkItemTypeData> entry : workItemTypes.entrySet()) {
				WorkItemTypeData data = entry.getValue();
				WorkItemTypeAttributes attributes = data.getWorkItemTypeAttributes();
				Map<String, WorkItemTypeField> fields = attributes.getFields();
				if (fields != null) {
					WorkItemTypeField state = fields.get("system.state"); //$NON-NLS-1
					if (state != null) {
						WorkItemTypeFieldType stateType = state.getType();
						for (String value : stateType.getValues()) {
							stateMap.put(value,  value);
						}
					}
				}
			}
			internalSetAttributeOptions(taskAttribute, stateMap);
		}
	}

	private void internalSetAttributeOptions(TaskAttribute taskAttribute, @SuppressWarnings("rawtypes") Map spaceMap) {
		boolean found = false;
		String actualValue = taskAttribute.getValue();
		for (Object entry : spaceMap.keySet()) {
			String option = (String)entry;
			taskAttribute.putOption(option, option);
			if (!found) {
				found = actualValue.equals(option);
			}

		}
		if (!found) {
			taskAttribute.setValue(""); //$NON-NLS-1$
		}

	}

	public boolean setSpaceOptions(@NonNull TaskData taskData, @NonNull Map<String, Space> spaces) {
		TaskAttribute attributeSpace = taskData.getRoot().getMappedAttribute(SCHEMA.SPACE.getKey());
		if (attributeSpace != null) {
			SortedSet<String> spaceSet = new TreeSet<String>();
			for (String key : spaces.keySet()) {
				spaceSet.add(key);
			}
			attributeSpace.clearOptions();
			for (String SpaceName : spaceSet) {
				attributeSpace.putOption(SpaceName, SpaceName);
			}
			return true;
		}
		return false;
	}

	public boolean updateSpaceOptions(@NonNull TaskData taskData) {
		if (taskData == null) {
			return false;
		}
		TaskAttribute attributeSpace = taskData.getRoot().getMappedAttribute(SCHEMA.SPACE.getKey());
		if (attributeSpace == null) {
			return false;
		}
		if (!attributeSpace.getValue().isEmpty()) {
			Space actualSpace = getSpaceWithName(attributeSpace.getValue());

			TaskAttribute attributeWorkItemType = taskData.getRoot().getMappedAttribute(SCHEMA.WORKITEM_TYPE.getKey());
			if (attributeWorkItemType != null) {
				setAttributeOptionsForSpace(attributeWorkItemType, actualSpace);
			}
			TaskAttribute attributeArea = taskData.getRoot().getMappedAttribute(SCHEMA.AREA.getKey());
			if (attributeArea != null) {
				setAttributeOptionsForSpace(attributeArea, actualSpace);
			}
			TaskAttribute attributeIteration = taskData.getRoot().getMappedAttribute(SCHEMA.ITERATION.getKey());
			if (attributeIteration != null) {
				setAttributeOptionsForSpace(attributeIteration, actualSpace);
			}
			TaskAttribute attributeAssignees = taskData.getRoot().getMappedAttribute(SCHEMA.ASSIGNEES.getKey());
			if (attributeAssignees != null) {
				setAttributeOptionsForSpace(attributeAssignees, actualSpace);
			}
			TaskAttribute attributeState = taskData.getRoot().getMappedAttribute(SCHEMA.STATUS.getKey());
			if (attributeState != null) {
				setAttributeOptionsForSpace(attributeState, actualSpace);
			}	
		} else {
			SortedSet<String> workItemTypes = new TreeSet<>();
			SortedSet<String> areas = new TreeSet<>();
			SortedSet<String> iterations = new TreeSet<>();
			SortedSet<String> users = new TreeSet<>();
			Set<String> states = new LinkedHashSet<>();
			for (Space space : getSpaces().values()) {
				attributeSpace.putOption(space.getName(), space.getName());
				if (space.getWorkItemTypes() != null) {
					// assume first workItemType is representative of all with regards to states
					if (!space.getWorkItemTypes().isEmpty()) {
						WorkItemTypeData data = space.getWorkItemTypes().values().iterator().next();
						WorkItemTypeAttributes attributes = data.getWorkItemTypeAttributes();
						Map<String, WorkItemTypeField> fields = attributes.getFields();
						WorkItemTypeField state = fields.get("system.state"); //$NON-NLS-1$
						WorkItemTypeFieldType stateType = state.getType();
						String[] values = stateType.getValues();
						if (values != null) {
							for (String value : values) {
								states.add(value);
							}
						}
					}
					for (Entry<String, WorkItemTypeData> entry : space.getWorkItemTypes().entrySet()) {
						workItemTypes.add(entry.getKey());
						WorkItemTypeData data = entry.getValue();
					}
				}
				if (space.getAreas() != null) {
					for (String entry : space.getAreas().keySet()) {
						areas.add(entry);
					}
				}
				if (space.getIterations() != null) {
					for (String entry : space.getIterations().keySet()) {
						iterations.add(entry);
					}
				}
				if (space.getUsers() != null) {
					for (String entry : space.getUsers().keySet()) {
						users.add(entry);
					}
				}
			}
			TaskAttribute attributeWorkItemType = taskData.getRoot().getMappedAttribute(SCHEMA.WORKITEM_TYPE.getKey());
			if (attributeWorkItemType != null) {
				setAllAttributeOptions(attributeWorkItemType, workItemTypes);
			}
			TaskAttribute attributeState = taskData.getRoot().getMappedAttribute(SCHEMA.STATUS.getKey());
			if (attributeState != null) {
				setAllAttributeOptions(attributeState, states);
			}

		}
		return true;
	}

	private void setAllAttributeOptions(TaskAttribute updateAttribute, Set<String> values) {
		for (String value : values) {
			updateAttribute.putOption(value, value);
		}
	}

	public void addValidOperations(TaskData workItem) {
		TaskAttribute attributeStatus = workItem.getRoot().getMappedAttribute(TaskAttribute.STATUS);
		String attributeStatusValue = attributeStatus.getValue();
		TaskAttribute operationAttribute = workItem.getRoot().getAttribute(TaskAttribute.OPERATION);
		if (operationAttribute == null) {
			operationAttribute = workItem.getRoot().createAttribute(TaskAttribute.OPERATION);
		}
		TaskAttribute attribute = workItem.getRoot()
				.createAttribute(TaskAttribute.PREFIX_OPERATION + attributeStatusValue);
		TaskOperation.applyTo(attribute, attributeStatusValue, 
				OSIORestMessages.getFormattedString("KeepStateOperation", attributeStatusValue)); //$NON-NLS-1$
		// set as default
		TaskOperation.applyTo(operationAttribute, attributeStatusValue, 
				OSIORestMessages.getFormattedString("KeepStateOperation", attributeStatusValue)); //$NON-NLS-1$
		for (String statusValue : statusValues) {
			if (attributeStatusValue == null ||
					(attributeStatusValue != null && attributeStatusValue.equals(statusValue))) {
				if (attributeStatusValue == null) {
					attributeStatusValue = ""; //$NON-NLS-1$
				}
				for (String transition : statusTransitions.get(statusValue)) {
					attribute = workItem.getRoot()
							.createAttribute(TaskAttribute.PREFIX_OPERATION + transition);
					TaskOperation.applyTo(attribute, transition, 
							OSIORestMessages.getFormattedString("StateChangeOperation", transition)); //$NON-NLS-1$
				}
			}
		}
	}

}