/*******************************************************************************
 * Copyright (c) 2007, 2008 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.validation.internal;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ISaveContext;
import org.eclipse.core.resources.ISaveParticipant;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.validation.DependentResource;
import org.eclipse.wst.validation.IDependencyIndex;
import org.eclipse.wst.validation.Validator;
import org.eclipse.wst.validation.internal.plugin.ValidationPlugin;

/**
 * A simple implementation of the IDependencyIndex. This will probably be
 * replaced with a higher performance, more robust index, at some point in the
 * future.
 * <p>
 * The format of the index is:
 * 
 * <pre>
 * Version number
 * Number of depends on entries
 *   depends on file name
 *   number of dependent entries
 *     dependent file name
 *     number of validators
 *       validator id
 * </pre>
 * 
 * @author karasiuk
 */
public class DependencyIndex implements IDependencyIndex, ISaveParticipant {
	
	/**
	 * An index so that we can determine which things depend on this resource.
	 */
	private Map<IResource,Set<Depends>>		_dependsOn;
	
	/**
	 * An index so that we can determine who the resource depends on.
	 */
	private Map<IResource,Set<Depends>>		_dependents;
	private boolean _dirty;
	
	private static IResource[] EmptyResources = new IResource[0];
	
	/** Version of the persistent index. */
	private static final int CurrentVersion = 1;

	public synchronized void add(String id, IResource dependent, IResource dependsOn) {
		init();
		Depends d = getOrCreateDepends(dependent, dependsOn);
		if (d.getValidators().add(id))_dirty = true;
	}
	
	private Depends getOrCreateDepends(IResource dependent, IResource dependsOn) {
		Set<Depends> set = getSet(_dependents, dependent);
		for (Depends d : set){
			if (d.getDependsOn().equals(dependsOn)) return d;
		}
		Depends d = new Depends(dependent, dependsOn);
		_dirty = true;
		set.add(d);
		
		getSet(_dependsOn, dependsOn).add(d);
		return d;
	}

	/**
	 * Answer the set for the resource, creating it if you need to.
	 */
	private Set<Depends> getSet(Map<IResource, Set<Depends>> map, IResource resource) {
		Set<Depends> set = map.get(resource);
		if (set == null){
			set = new HashSet<Depends>(5);
			map.put(resource, set);
		}
		return set;
	}

	/**
	 * Restore the dependency index. See the class comment for the structure.
	 */	
	private void init() {
		if (_dependsOn != null)return;
		
		boolean error = false;
		File f = getIndexLocation();
		if (!f.exists()){
			_dependsOn = new HashMap<IResource,Set<Depends>>(100);
			_dependents = new HashMap<IResource,Set<Depends>>(100);
		}
		else {
			String errorMessage = "The following dependency could not be restored " + //$NON-NLS-1$
				"because the following resource {0} could no longer be found."; //$NON-NLS-1$
			DataInputStream in = null;
			try {
				IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
				in = new DataInputStream(new FileInputStream(f));
				
				int version = in.readInt();
				if (version != CurrentVersion){
					error = true;
					String msg = NLS.bind(ValMessages.ErrDependencyVersion, CurrentVersion);
					throw new IllegalStateException(msg);
				}
				int numDependsOn = in.readInt();
				_dependsOn = new HashMap<IResource,Set<Depends>>(numDependsOn+100);
				_dependents = new HashMap<IResource,Set<Depends>>(numDependsOn+100);
				for (int i=0; i<numDependsOn; i++){
					String v = in.readUTF();
					IResource dependsOn = root.findMember(v);
					if (v == null){
						Tracing.log(NLS.bind(errorMessage, v));
						continue;
					}
					int numDependents = in.readInt();
					for (int j=0; j<numDependents; j++){
						v = in.readUTF();
						IResource dependent = root.findMember(v);
						if (dependent == null){
							Tracing.log(NLS.bind(errorMessage, v));
							continue;
						}
						int numVal = in.readInt();
						for (int k=0; k<numVal; k++){
							String id = in.readUTF();
							add(id, dependent, dependsOn);
						}
					}					
				}				
			}
			catch (IOException e){
				error = true;
				ValidationPlugin.getPlugin().handleException(e);
			}
			finally {
				Misc.close(in);
				if (error){
					_dependsOn = new HashMap<IResource,Set<Depends>>(100);
					_dependents = new HashMap<IResource,Set<Depends>>(100);
					f.delete();
				}
			}			
		}
	}

	public synchronized void clear(IProject project) {
		init();
		for (Map.Entry<IResource,Set<Depends>> me : _dependents.entrySet()){
			if (me.getKey().getProject() == project){
				for (Depends d : me.getValue()){
					if (d.delete())_dirty = true;
				}
			}
		}
	}

	public synchronized IResource[] get(String validatorId, IResource dependsOn) {
		init();
		List<IResource> list = new LinkedList<IResource>();
		Set<Depends> set = getSet(_dependsOn, dependsOn);
		for (Depends d : set){
			for (String id : d.getValidators()){
				if (validatorId.equals(id))list.add(d.getDependent());
			}
		}
		
		if (list.size() == 0)return EmptyResources;
		IResource[] resources = new IResource[list.size()];
		list.toArray(resources);
		return resources;
	}

	
	public synchronized List<DependentResource> get(IResource dependsOn) {
		init();
		List<DependentResource> list = new LinkedList<DependentResource>();
		Set<Depends> set = getSet(_dependsOn, dependsOn);
		ValManager vm = ValManager.getDefault();
		for (Depends d : set){
			for (String id : d.getValidators()){
				Validator v = vm.getValidator(id, d.getDependent().getProject());
				if (v != null)list.add(new DependentResource(d.getDependent(), v));
			}
		}
		return list;
	}


	public synchronized void set(String id, IResource dependent, IResource[] dependsOn) {
		init();
		Set<Depends> set = getSet(_dependents, dependent);
		for (Depends d : set){
			if (d.delete(id))_dirty = true;
		}
		if (dependsOn != null){
			for (IResource d : dependsOn)add(id, dependent, d);
		}
	}
		
	public boolean isDependedOn(IResource resource) {
		init();
		Set<Depends> set = _dependsOn.get(resource);
		if (set == null || set.size() == 0)return false;
		return true;
	}

	public void doneSaving(ISaveContext context) {	
	}
	
	public void prepareToSave(ISaveContext context) throws CoreException {	
	}
	
	public void rollback(ISaveContext context) {
	}
	
	/**
	 * Persist the dependency index. See the class comment for the structure.
	 */
	public synchronized void saving(ISaveContext context) throws CoreException {
		if (!_dirty)return;
		_dirty = false;
		
		DataOutputStream out = null;
		try {
			File f = getIndexLocation();
			out = new DataOutputStream(new FileOutputStream(f));
			out.writeInt(CurrentVersion);
			Map<String, Set<DependsResolved>> map = compress(_dependsOn);
			out.writeInt(map.size());
			for (Map.Entry<String, Set<DependsResolved>> me : map.entrySet()){
				out.writeUTF(me.getKey());
				Set<DependsResolved> set = me.getValue();
				out.writeInt(set.size());
				for (DependsResolved d : set){
					out.writeUTF(d.resource);
					out.writeInt(d.validators.size());
					for (String id : d.validators){
						out.writeUTF(id);
					}
				}
			}
		}
		catch (IOException e){
			ValidationPlugin.getPlugin().handleException(e);
		}
		finally {
			Misc.close(out);
		}
	}

	private Map<String, Set<DependsResolved>> compress(Map<IResource, Set<Depends>> dependsOn) {
		Map<String, Set<DependsResolved>> map = new HashMap<String, Set<DependsResolved>>(dependsOn.size());
		for (Map.Entry<IResource, Set<Depends>> me : dependsOn.entrySet()){
			Set<DependsResolved> set = new HashSet<DependsResolved>(me.getValue().size());
			for (Depends d : me.getValue()){
				IPath path = d.getDependent().getFullPath();
				if (path != null){
					DependsResolved dr = new DependsResolved();
					dr.resource = path.toPortableString();
					if (d.getValidators().size() > 0){
						dr.validators = d.getValidators();
						set.add(dr);
					}
				}				
			}
			if (set.size() > 0){
				IResource res = me.getKey();
				if (res != null){
					IPath path = res.getFullPath();
					if (path != null)map.put(path.toPortableString(), set);
				}
			}
		}
		return map;
	}

	private File getIndexLocation() {
		IPath path = ValidationPlugin.getPlugin().getStateLocation().append("dep.index"); //$NON-NLS-1$
		return path.toFile();
	}

	/**
	 * Keep track of a relationship between a dependent and the thing that it
	 * depends on.
	 * 
	 * @author karasiuk
	 * 
	 */
	private static class Depends {

		/** The resource that is being depended on, for example a.xsd */
		private IResource _dependsOn;

		/** The resource that is dependent, for example a.xml */
		private IResource _dependent;

		/** The id's of the validators that have asserted the dependency. */
		private Set<String> _validators;

		public Depends(IResource dependent, IResource dependsOn) {
			_dependent = dependent;
			_dependsOn = dependsOn;
			_validators = new HashSet<String>(5);
		}

		/**
		 * Answer true if the id was deleted.
		 */
		public boolean delete(String id) {
			return _validators.remove(id);
		}

		/**
		 * Delete all the dependency assertions for all of your validators.
		 * @return false if there was nothing to delete
		 */
		public boolean delete() {
			boolean deleted = _validators.size() > 0;
			if (deleted)_validators.clear();
			return deleted;
		}

		public IResource getDependsOn() {
			return _dependsOn;
		}

		public IResource getDependent() {
			return _dependent;
		}

		public Set<String> getValidators() {
			return _validators;
		}
}

	private static class DependsResolved {
		String 		resource;
		Set<String> validators;
	}


}
