/*******************************************************************************
 * Copyright (c) 2009 SAP AG.
 * 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:
 *    Eduard Bartsch (SAP AG) - initial API and implementation
 *    Mathias Kinzler (SAP AG) - initial API and implementation
 *******************************************************************************/
package org.eclipse.core.internal.resources.semantic;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.core.filesystem.provider.FileStore;
import org.eclipse.core.internal.resources.semantic.model.SemanticResourceDB.ResourceTreeNode;
import org.eclipse.core.resources.semantic.ISemanticProperties;
import org.eclipse.core.resources.semantic.SemanticResourceException;
import org.eclipse.core.resources.semantic.SemanticResourceStatusCode;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;

/**
 * The {@link ISemanticProperties} implementation.
 * 
 */
public abstract class SemanticProperties extends FileStore implements ISemanticProperties {

	protected ResourceTreeNode node;
	protected final SemanticFileSystem fs;

	SemanticProperties(SemanticFileSystem fs, ResourceTreeNode node) {
		this.fs = fs;
		this.node = node;
	}

	private IPath getPathForTrace() {
		try {
			return this.fs.getPathForNode(this.node);
		} catch (RuntimeException rte) {
			// $JL-EXC$
			return new Path(this.node.getName());
		}
	}

	/**
	 * @throws CoreException
	 */
	public Map<QualifiedName, String> getPersistentProperties() throws CoreException {

		if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
			SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_VERBOSE.getLocation(), getPathForTrace().toString());
		}

		checkAccessible();

		Map<QualifiedName, String> result = new HashMap<QualifiedName, String>();
		try {
			this.fs.lockForRead();
			HashMap<String, String> atts = this.node.getPersistentProperties();
			if (atts == null) {
				return result;
			}
			for (Map.Entry<String, String> entry : atts.entrySet()) {
				String qualifier;
				String localName;
				int index = entry.getKey().indexOf('^');
				if (index > 0) {
					qualifier = entry.getKey().substring(0, index);
					localName = entry.getKey().substring(index + 1);
				} else {
					qualifier = null;
					localName = entry.getKey();
				}
				result.put(new QualifiedName(qualifier, localName), entry.getValue());
			}

			return result;
		} finally {
			this.fs.unlockForRead();
			if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
				SfsTraceLocation.getTrace().traceExit(SfsTraceLocation.CORE_VERBOSE.getLocation(), result);
			}
		}

	}

	/**
	 * @throws CoreException
	 */
	public String getPersistentProperty(QualifiedName key) throws CoreException {

		if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
			SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_VERBOSE.getLocation(),
					new Object[] {getPathForTrace().toString(), key});
		}

		String result = null;
		try {
			this.fs.lockForRead();
			HashMap<String, String> nodeProps = this.node.getPersistentProperties();
			if (nodeProps == null) {
				return result;
			}
			String keyString = Util.qualifiedNameToString(key);
			result = nodeProps.get(keyString);

			return result;
		} finally {
			this.fs.unlockForRead();
			if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
				SfsTraceLocation.getTrace().traceExit(SfsTraceLocation.CORE_VERBOSE.getLocation(), result);
			}
		}

	}

	public void setPersistentProperty(QualifiedName key, String value) throws CoreException {

		if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
			SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_VERBOSE.getLocation(), getPathForTrace().toString());
		}

		checkAccessible();

		Util.assertQualifiedNameValid(key);

		String keyString = Util.qualifiedNameToString(key);
		try {
			this.fs.lockForWrite();

			String oldValue = null;

			HashMap<String, String> map = this.node.getPersistentProperties();
			if (map == null) {
				map = new HashMap<String, String>();
			} else {
				oldValue = map.get(keyString);
			}

			if (!isEqualValue(value, oldValue)) {
				if (value != null) {
					map.put(keyString, value);
				} else {
					map.remove(keyString);
				}
				this.node.setPersistentProperties(map);

				this.notifyPersistentPropertySet(keyString, oldValue, value);

				this.fs.requestFlush(false);
			}
		} finally {
			this.fs.unlockForWrite();
		}

	}

	public void updatePersistentProperties(Map<QualifiedName, String> propertiesToBeAddedOrUpdated,
			List<QualifiedName> propertiesToBeDeleted) throws CoreException {
		if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
			SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_VERBOSE.getLocation(), getPathForTrace().toString());
		}

		checkAccessible();

		// check all keys to be added/updated
		if (propertiesToBeAddedOrUpdated != null) {
			for (QualifiedName key : propertiesToBeAddedOrUpdated.keySet()) {
				Util.assertQualifiedNameValid(key);
			}
		}

		try {
			this.fs.lockForWrite();

			boolean needsFlush = false;

			HashMap<String, String> map = this.node.getPersistentProperties();
			if (map == null) {
				map = new HashMap<String, String>();
			}

			if (propertiesToBeDeleted != null) {
				for (QualifiedName key : propertiesToBeDeleted) {
					String keyString = Util.qualifiedNameToString(key);
					if (map.get(keyString) != null) {
						map.remove(keyString);
						needsFlush = true;
					}
				}
			}

			if (propertiesToBeAddedOrUpdated != null) {
				for (Entry<QualifiedName, String> entry : propertiesToBeAddedOrUpdated.entrySet()) {
					String keyString = Util.qualifiedNameToString(entry.getKey());
					String oldValue = null;

					oldValue = map.get(keyString);

					if (!isEqualValue(entry.getValue(), oldValue) && entry.getValue() != null) {
						map.put(keyString, entry.getValue());

						this.notifyPersistentPropertySet(keyString, oldValue, entry.getValue());

						needsFlush = true;
					}
				}
			}
			if (needsFlush) {
				this.node.setPersistentProperties(map);

				this.fs.requestFlush(false);
			}
		} finally {
			this.fs.unlockForWrite();
		}
	}

	protected abstract void notifyPersistentPropertySet(String keyString, String oldValue, String newValue) throws CoreException;

	/**
	 * @throws CoreException
	 */
	public void setSessionProperty(QualifiedName key, Object value) throws CoreException {

		if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
			SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_VERBOSE.getLocation(), getPathForTrace().toString());
		}

		checkAccessible();

		Util.assertQualifiedNameValid(key);

		try {
			this.fs.lockForWrite();

			HashMap<QualifiedName, Object> map = this.node.getSessionProperties();
			if (map == null) {
				map = new HashMap<QualifiedName, Object>();
				this.node.setSessionProperties(map);
			}
			if (value != null) {
				map.put(key, value);
			} else {
				map.remove(key);
			}

		} finally {
			this.fs.unlockForWrite();
		}

	}

	/**
	 * @throws CoreException
	 */
	public Map<QualifiedName, Object> getSessionProperties() throws CoreException {

		if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
			SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_VERBOSE.getLocation(), getPathForTrace().toString());
		}

		checkAccessible();

		Map<QualifiedName, Object> result = new HashMap<QualifiedName, Object>();

		try {
			this.fs.lockForRead();
			HashMap<QualifiedName, Object> atts = this.node.getSessionProperties();
			if (atts == null) {
				return result;
			}
			// we copy the map here (QualifiedName is immutable)
			for (Map.Entry<QualifiedName, Object> entry : atts.entrySet()) {
				result.put(entry.getKey(), entry.getValue());
			}

			return result;
		} finally {
			this.fs.unlockForRead();
			if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
				SfsTraceLocation.getTrace().traceExit(SfsTraceLocation.CORE_VERBOSE.getLocation(), result);
			}
		}
	}

	/**
	 * @throws CoreException
	 */
	public Object getSessionProperty(QualifiedName key) throws CoreException {

		if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
			SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_VERBOSE.getLocation(),
					new Object[] {getPathForTrace().toString(), key});
		}

		Object result = null;
		try {
			this.fs.lockForRead();
			HashMap<QualifiedName, Object> nodeProps = this.node.getSessionProperties();
			if (nodeProps == null) {
				return result;
			}
			result = nodeProps.get(key);
			return result;
		} finally {
			this.fs.unlockForRead();
			if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
				SfsTraceLocation.getTrace().traceExit(SfsTraceLocation.CORE_VERBOSE.getLocation(), result);
			}
		}
	}

	/**
	 * Similar to
	 * <code>org.eclipse.core.internal.resources.Resource#checkAccessible(int)</code>
	 * <p>
	 * The corresponding Resource method is called on:
	 * <ul>
	 * <li>Container.memebers()</li>
	 * <li>Container.setDefaultCharset()</li>
	 * <li>File.appendContents()</li>
	 * <li>File.create() (on the parent)</li>
	 * <li>File.getContentDescription()</li>
	 * <li>File.getContents()</li>
	 * <li>File.getEncoding()</li>
	 * <li>File.setCharset()</li>
	 * <li>File.setContents()</li>
	 * <li>Folder.create() (on the parent)</li>
	 * <li>Project.checkAccessible()</li>
	 * <li>Project.getDescription()</li>
	 * <li>Project.getNature()</li>
	 * <li>Project.getReferencedProjects()</li>
	 * <li>Project.hasNature</li>
	 * <li>Project.isNatureEnabled()</li>
	 * <li>Project.setDescription()</li>
	 * <li>Resource.accept()</li>
	 * <li>Resource.createLink()</li>
	 * <li>Resource.copy()</li>
	 * <li>Resource.move()</li>
	 * <li>Resource.createMarker()</li>
	 * <li>Resource.deleteMarkers()</li>
	 * <li>Resource.findMarkers()</li>
	 * <li>Resource.findMaxProblemSeverity()</li>
	 * <li>Resource.setDerived()</li>
	 * <li>Resource.setHidden()</li>
	 * <li>Resource.setTeamPrivateMember()</li>
	 * </ul>
	 * 
	 * @throws CoreException
	 */
	protected void checkAccessible() throws CoreException {
		checkAndJoinTreeIfAnotherEntryExists();

		if (!this.node.isExists()) {
			throw new SemanticResourceException(SemanticResourceStatusCode.NOT_ACCESSIBLE, getPathForTrace(),
					Messages.SemanticProperties_StoreNotAccessible_XMSG);
		}
	}

	protected void checkAndJoinTreeIfAnotherEntryExists() {
		try {
			this.fs.lockForRead();
			if (!this.node.isExists()) {
				ResourceTreeNode other = this.fs.getNodeByPath(this.node.getPath());

				if (other.isExists()) {
					this.node = other;
				}
			}
		} finally {
			this.fs.unlockForRead();
			if (SfsTraceLocation.CORE_VERBOSE.isActive()) {
				SfsTraceLocation.getTrace().traceExit(SfsTraceLocation.CORE_VERBOSE.getLocation());
			}
		}
	}

	private boolean isEqualValue(String value, String oldValue) {
		if (value == null && oldValue == null) {
			return true;
		} else if (value != null && oldValue == null) {
			return false;
		} else if (value == null && oldValue != null) {
			return false;
		}
		return value.equals(oldValue);
	}

}
