/*******************************************************************************
 * Copyright (c) 2005, 2007 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.server.core.internal;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.IPath;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.ServerUtil;
import org.eclipse.wst.server.core.model.IModuleFile;
import org.eclipse.wst.server.core.model.IModuleFolder;
import org.eclipse.wst.server.core.model.IModuleResource;
import org.eclipse.wst.server.core.model.IModuleResourceDelta;
/**
 * Helper to obtain and store the publishing information (what files
 * were published and when) for a single server.
 */
public class ServerPublishInfo {
	private static final String VERSION = "version";

	protected IPath path;

	// map of module ids to ModulePublishInfo
	protected Map<String, ModulePublishInfo> modulePublishInfo;

	/**
	 * ServerPublishInfo constructor comment.
	 */
	protected ServerPublishInfo(IPath path) {
		super();
		
		this.path = path;
		modulePublishInfo = new HashMap<String, ModulePublishInfo>();
		load();
	}

	private String getKey(IModule[] module) {
		StringBuffer sb = new StringBuffer();
		
		if (module != null) {
			int size = module.length;
			for (int i = 0; i < size; i++) {
				if (i != 0)
					sb.append("#");
				if (module[i] != null)
					sb.append(module[i].getId());
				else
					sb.append("null");
			}
		}
		
		return sb.toString();
	}

	private String getKey(String moduleId) {
		return moduleId;
	}

	private IModule[] getModule(String moduleId) {
		if (moduleId == null || moduleId.length() == 0)
			return new IModule[0];
		
		List<IModule> list = new ArrayList<IModule>();
		StringTokenizer st = new StringTokenizer(moduleId, "#");
		while (st.hasMoreTokens()) {
			String mid = st.nextToken();
			if (mid != null && mid.length() > 0) {
				IModule m = ServerUtil.getModule(mid);
				if (m == null)
					return null;
				list.add(m);
			}
		}
		
		IModule[] modules = new IModule[list.size()];
		list.toArray(modules);
		return modules;
	}

	public boolean hasModulePublishInfo(IModule[] module) {
		String key = getKey(module);
		return modulePublishInfo.containsKey(key);
	}

	/*public void removeModulePublishInfo(IModule[] module) {
		String key = getKey(module);
		modulePublishInfo.remove(key);
		
		save();
	}*/

	/**
	 * 
	 * Note: save() must be called manually after making this call.
	 * 
	 * @param moduleList
	 * @deprecated Use removeDeletedModulePublishInfo(Server, List) instead
	 */
	public void removeDeletedModulePublishInfo(List moduleList) {
		removeDeletedModulePublishInfo(null, moduleList);
	}

	/**
	 * Removes successfully deleted modules from the next publish.
	 * Note: save() must be called manually after making this call.
	 * 
	 * @param server a server
	 * @param moduleList the modules currently on the server
	 */
	public void removeDeletedModulePublishInfo(Server server, List moduleList) {
		int size = moduleList.size();
		List<String> removed = new ArrayList<String>();
		
		Iterator iterator = modulePublishInfo.keySet().iterator();
		while (iterator.hasNext()) {
			String key = (String) iterator.next();
			
			boolean found = false;
			for (int i = 0; i < size; i++) {
				IModule[] module = (IModule[]) moduleList.get(i);
				String key2 = getKey(module);
				if (key != null && key.equals(key2))
					found = true;
			}
			
			if (server != null) {
				try {
					Integer in = server.modulePublishState.get(key);
					if (in != null && in.intValue() != IServer.PUBLISH_STATE_NONE)
						found = true;
				} catch (Exception e) {
					// ignore
				}
			}
			
			if (!found)
				removed.add(key);
		}
		
		iterator = removed.iterator();
		while (iterator.hasNext()) {
			String key = (String) iterator.next();
			modulePublishInfo.remove(key);
		}
	}

	/**
	 * Return the publish state.
	 */
	protected ModulePublishInfo getModulePublishInfo(IModule[] module) {
		String key = getKey(module);
		
		// check if it now exists
		if (modulePublishInfo.containsKey(key))
			return modulePublishInfo.get(key);
		
		// have to create a new one
		IModule mod = module[module.length - 1];
		ModulePublishInfo mpi = new ModulePublishInfo(getKey(module), mod.getName(), mod.getModuleType());
		modulePublishInfo.put(key, mpi);
		return mpi;
	}

	public void addRemovedModules(List<IModule[]> moduleList) {
		int size = moduleList.size();
		List<ModulePublishInfo> removed = new ArrayList<ModulePublishInfo>();
		Iterator iterator = modulePublishInfo.keySet().iterator();
		while (iterator.hasNext()) {
			String key = (String) iterator.next();
		
			boolean found = false;
			for (int i = 0; i < size; i++) {
				IModule[] module = moduleList.get(i);
				String key2 = getKey(module);
				if (key != null && key.equals(key2))
					found = true;
			}
			if (!found) {
				ModulePublishInfo mpi = modulePublishInfo.get(key);
				removed.add(mpi);
			}
		}
		
		iterator = removed.iterator();
		while (iterator.hasNext()) {
			ModulePublishInfo mpi = (ModulePublishInfo) iterator.next();
			IModule[] module2 = getModule(mpi.getModuleId());
			if (module2 == null || module2.length == 0) {
				String moduleId = mpi.getModuleId();
				if (moduleId != null) {
					String[] ids = getModuleIds(moduleId);
					int depth = ids.length;
					
					module2 = new IModule[depth];
					String s = "";
					for (int i = 0; i < depth; i++) {
						s += ids[i];
						if (i == depth - 1)
							module2[i] = mpi.getDeletedModule();
						else {
							ModulePublishInfo mpi2 = modulePublishInfo.get(s);
							if (mpi2 != null)
								module2[i] = mpi2.getDeletedModule();
						}
						s += "#";
					}
				}
			}
			if (module2 != null && module2.length > 0)
				moduleList.add(module2);
		}
	}

	/**
	 * Parse a combined module id string into the individual module ids
	 * @param moduleId
	 * @return an array of module ids
	 */
	private String[] getModuleIds(String moduleId) {
		StringTokenizer st = new StringTokenizer(moduleId, "#");
		List<String> list = new ArrayList<String>(2);
		while (st.hasMoreTokens()) {
			list.add(st.nextToken());
		}
		
		String[] s = new String[list.size()];
		list.toArray(s);
		return s;
	}

	/**
	 * 
	 */
	public void load() {
		String filename = path.toOSString();
		
		if (new File(filename).exists()) {
			Trace.trace(Trace.FINEST, "Loading publish info from " + filename);
			
			DataInputStream in = null;
			try {
				in = new DataInputStream(new BufferedInputStream(new FileInputStream(filename)));
				in.readByte();
				in.readByte();
				// version
				int ver = in.readByte();
				if (ver <= 1) {
					int size = in.readInt();	
					for (int i = 0; i < size; i++) {
						ModulePublishInfo mpi = new ModulePublishInfo(in);
						modulePublishInfo.put(getKey(mpi.getModuleId()), mpi);
					}
					return;
				}
			} catch (Exception e) {
				Trace.trace(Trace.WARNING, "Could not load publish information", e);
			}
		}
		
		filename = filename.substring(0, filename.length() - 3) + "xml";
		if (new File(filename).exists()) {
			Trace.trace(Trace.FINEST, "Loading publish info from old format " + filename);
			
			try {
				IMemento memento2 = XMLMemento.loadMemento(filename);
				Float f = memento2.getFloat(VERSION);
				if (f != null && f.floatValue() >= 3)
					return;
				
				IMemento[] children = memento2.getChildren("module");
				
				int size = children.length;
				for (int i = 0; i < size; i++) {
					ModulePublishInfo mpi = new ModulePublishInfo(children[i]);
					modulePublishInfo.put(getKey(mpi.getModuleId()), mpi);
				}
			} catch (Exception e) {
				Trace.trace(Trace.WARNING, "Could not load publish information", e);
			}
		}
	}

	/**
	 * 
	 */
	public void save() {
		String filename = path.toOSString();
		Trace.trace(Trace.FINEST, "Saving publish info to " + filename);
		
		DataOutputStream out = null;
		try {
			out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename)));
			out.writeByte(14);
			out.writeByte(14);
			// version
			out.writeByte(1);
			
			out.writeInt(modulePublishInfo.keySet().size());
			Iterator iterator = modulePublishInfo.keySet().iterator();
			while (iterator.hasNext()) {
				String controlRef = (String) iterator.next();
				ModulePublishInfo mpi = modulePublishInfo.get(controlRef);
				mpi.save(out);
			}
		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Could not save publish information", e);
		} finally {
			try {
				if (out != null)
					out.close();
			} catch (Exception e) {
				// ignore
			}
		}
		
		// remove old file
		filename = filename.substring(0, filename.length() - 3) + "xml";
		File f = new File(filename);
		if (f.exists())
			f.delete();
	}

	/**
	 * 
	 * Note: save() must be called manually after making this call.
	 * @param module
	 */
	public void fill(IModule[] module) {
		ModulePublishInfo mpi = getModulePublishInfo(module);
		mpi.fill(module);
	}

	protected IModuleResourceDelta[] getDelta(IModule[] module) {
		if (module == null)
			return new IModuleResourceDelta[0];
		
		return getModulePublishInfo(module).getDelta(module);
	}

	protected IModuleResource[] getResources(IModule[] module) {
		if (module == null)
			return new IModuleResource[0];
		
		return getModulePublishInfo(module).getModuleResources(module);
	}

	protected static IModuleResourceDelta[] getDelta(IModuleResource[] original, IModuleResource[] current) {
		if (original == null || current == null)
			return new IModuleResourceDelta[0];
		
		List<ModuleResourceDelta> list = new ArrayList<ModuleResourceDelta>();
		int size = original.length;
		int size2 = current.length;
		
		Map<IModuleResource, IModuleResource> originalMap = new HashMap<IModuleResource, IModuleResource>(size);
		for (int i = 0; i < size; i++)
			originalMap.put(original[i], original[i]);
		
		// added and changed resources
		for (int i = 0; i < size2; i++) {
			IModuleResource old = originalMap.remove(current[i]);
			if (old == null) {
				ModuleResourceDelta delta = new ModuleResourceDelta(current[i], IModuleResourceDelta.ADDED);
				if (current[i] instanceof IModuleFolder) {
					IModuleFolder currentFolder = (IModuleFolder) current[i]; 
					delta.setChildren(getDeltaTree(currentFolder.members(), IModuleResourceDelta.ADDED));
				}
				list.add(delta);
			} else {
				if (current[i] instanceof IModuleFile) {
					// include files only if the modification stamp has changed
					IModuleFile mf1 = (IModuleFile) old;
					IModuleFile mf2 = (IModuleFile) current[i];
					if (mf1.getModificationStamp() != mf2.getModificationStamp()) {
						list.add(new ModuleResourceDelta(current[i], IModuleResourceDelta.CHANGED));
					}
				} else {
					// include folders only if their contents have changed
					IModuleFolder mf1 = (IModuleFolder) old;
					IModuleFolder mf2 = (IModuleFolder) current[i];
					IModuleResourceDelta[] mrdc = getDelta(mf1.members(), mf2.members());
					if (mrdc.length > 0) {
						ModuleResourceDelta mrd = new ModuleResourceDelta(current[i], IModuleResourceDelta.NO_CHANGE);
						mrd.setChildren(mrdc);
						list.add(mrd);
					}
				}
			}
		}
		
		// removed resources
		for (int i = 0; i < size; i++) {
			if (originalMap.containsKey(original[i])) {
				ModuleResourceDelta delta = new ModuleResourceDelta(original[i], IModuleResourceDelta.REMOVED);
				if (original[i] instanceof IModuleFolder) {
					IModuleFolder removedFolder = (IModuleFolder) original[i]; 
					delta.setChildren(getDeltaTree(removedFolder.members(), IModuleResourceDelta.REMOVED));
				}
				list.add(delta);
			}
		}
		
		return list.toArray(new IModuleResourceDelta[list.size()]);
	}

	protected boolean hasDelta(IModule[] module) {
		if (module == null)
			return false;
		
		return hasModulePublishInfo(module) 
            && getModulePublishInfo(module).hasDelta(module);
	}

	protected static boolean hasDelta(IModuleResource[] original, IModuleResource[] current) {
		if (original == null || current == null)
			return false;
		
		int size = original.length;
		int size2 = current.length;
		
		Map<IModuleResource, IModuleResource> originalMap = new HashMap<IModuleResource, IModuleResource>(size);
		for (int i = 0; i < size; i++)
			originalMap.put(original[i], original[i]);
		
		// added and changed resources
		for (int i = 0; i < size2; i++) {
			IModuleResource old = originalMap.remove(current[i]);
			if (old == null)
				return true;
			
			if (current[i] instanceof IModuleFile) {
				// include files only if the modification stamp has changed
				IModuleFile mf1 = (IModuleFile) old;
				IModuleFile mf2 = (IModuleFile) current[i];
				if (mf1.getModificationStamp() != mf2.getModificationStamp())
					return true;
			} else {
				// include folders only if their contents have changed
				IModuleFolder mf1 = (IModuleFolder) old;
				IModuleFolder mf2 = (IModuleFolder) current[i];
				if (hasDelta(mf1.members(), mf2.members()))
					return true;
			}
		}
		
		// removed resources
		return !originalMap.isEmpty();
	}

	/**
	 * Create a resource delta for an entire tree.
	 */
	private static IModuleResourceDelta[] getDeltaTree(IModuleResource[] resources, int kind) {
		if (resources == null)
			return new IModuleResourceDelta[0];
		
		List<ModuleResourceDelta> list = new ArrayList<ModuleResourceDelta>();
		
		// look for duplicates
		int size = resources.length;
		for (int i = 0; i < size; i++) {
			ModuleResourceDelta mrd = new ModuleResourceDelta(resources[i], kind);
			if (resources[i] instanceof IModuleFolder) {
				IModuleFolder mf = (IModuleFolder) resources[i];
				mrd.setChildren(getDeltaTree(mf.members(), kind));
			}
			list.add(mrd);
		}
		
		return list.toArray(new IModuleResourceDelta[list.size()]);
	}

	/**
	 * Returns true if the list of modules being published does not match the previous
	 * list of published modules.
	 * 
	 * This method should compare the modules. For now, comparing the size is fine.
	 * 
	 * @param modules a list of modules
	 * @return <code>true</code> if the structure of published modules has changed, or
	 *    <code>false</code> otherwise
	 */
	protected boolean hasStructureChanged(List modules) {
		return modules.size() != modulePublishInfo.keySet().size();
	}

	/**
	 * Fill the module cache.
	 */
	public void startCaching() {
		Iterator iterator = modulePublishInfo.values().iterator();
		while (iterator.hasNext()) {
			ModulePublishInfo mpi = (ModulePublishInfo) iterator.next();
			mpi.startCaching();
		}
	}

	/**
	 * Clears all caches of current module resources and deltas.
	 */
	public void clearCache() {
		Iterator iterator = modulePublishInfo.values().iterator();
		while (iterator.hasNext()) {
			ModulePublishInfo mpi = (ModulePublishInfo) iterator.next();
			mpi.clearCache();
		}
	}
}