/*******************************************************************************
 * 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();
		if (dependsOn == null || dependent == null)return;
		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() != null && 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 " + 
				"because the following resource {0} could no longer be found."; 
			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 (dependsOn == null){
						Tracing.log(NLS.bind(errorMessage, v));
					}
					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));
						}
						int numVal = in.readInt();
						for (int k=0; k<numVal; k++){
							String id = in.readUTF();
							if (dependent != null && dependsOn != null)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;
	}


}
