/*******************************************************************************
 * Copyright (c) 2003, 2006 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.jst.common.jdt.internal.integration;



import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jst.common.frameworks.CommonFrameworksPlugin;
import org.eclipse.wst.common.frameworks.internal.ISaveHandler;
import org.eclipse.wst.common.frameworks.internal.SaveFailedException;
import org.eclipse.wst.common.frameworks.internal.SaveHandlerHeadless;
import org.eclipse.wst.common.frameworks.internal.SaveHandlerRegister;
import org.eclipse.wst.common.frameworks.internal.plugin.WTPCommonPlugin;

/**
 * Insert the type's description here. Creation date: (4/27/2001 4:14:30 PM)
 * 
 * @author: Administrator
 */
public class WTPWorkingCopyManager implements WorkingCopyManager {

	//New CUs that will need to be deleted upon dispose
	private List originalNewCompilationUnits;
	//New CUs that were created that need saved immediately (after each gen)
	private List needsSavingCompilationUnits;
	//A complete list of new CUs that is only cleared on save and dispose
	private List newCompilationUnits;
	private HashMap deletedCompilationUnits;
	protected static final Class IRESOURCE_CLASS = IResource.class;

	/**
	 * WTPWorkingCopyManager constructor comment.
	 */
	public WTPWorkingCopyManager() {
		super();
	}

	protected void addDeletedCompilationUnit(ICompilationUnit cu) {
		getNeedsSavingCompilationUnits().remove(cu);
		if (!getOriginalNewCompilationUnits().contains(cu) && !getDeletedCompilationUnits().containsKey(cu))
			primAddDeletedCompilationUnit(cu);
		getOriginalNewCompilationUnits().remove(cu);
	}

	protected void addNewCompilationUnit(ICompilationUnit cu, ICompilationUnit workingCopy) {
		getNewCompilationUnits().add(cu);
		getNeedsSavingCompilationUnits().add(workingCopy);
		if (!getDeletedCompilationUnits().containsKey(cu))
			getOriginalNewCompilationUnits().add(cu);
	}

	/**
	 * This will save all of the new CompilationUnits to be saved.
	 */
	protected void commitWorkingCopy(ICompilationUnit wc, IProgressMonitor monitor) {
		try {
			try {
				wc.commitWorkingCopy(false, monitor);
			} catch (JavaModelException e) {
				if (isFailedWriteFileFailure(e) && shouldSaveReadOnly(wc))
					wc.commitWorkingCopy(false, monitor);
				else
					throw e;
			}
		} catch (JavaModelException e) {
			org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(e);
			throw new SaveFailedException(e);
		} finally {
			try {
				wc.discardWorkingCopy();
			} catch (JavaModelException e1) {
				org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(e1);
				throw new SaveFailedException(e1);
			}
		}
	}

	/**
	 * This will delete
	 * 
	 * @cu from the workbench and fix the internal references for this working copy manager.
	 */
	public void delete(final ICompilationUnit cu, final IProgressMonitor monitor) {
		ICompilationUnit localCU = cu;
		if (localCU.isWorkingCopy())
			localCU = localCU.getPrimary();
		addDeletedCompilationUnit(localCU);
		try {
			localCU.delete(false, monitor);
		} catch (JavaModelException e) {
			if (e.getStatus().getCode() != org.eclipse.jdt.core.IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST)
				org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(e);
		}
	}

	protected void discardOriginalNewCompilationUnits() {
		if (getOriginalNewCompilationUnits().isEmpty())
			return;
		List cus = getOriginalNewCompilationUnits();
		ICompilationUnit cu;
		ICompilationUnit wc = null;
		for (int i = 0; i < cus.size(); i++) {
			cu = (ICompilationUnit) cus.get(i);
			if (cu.isWorkingCopy()) {
				wc = cu;
				cu = wc.getPrimary();
			}
			primDelete(cu);
			if (wc != null)
				try {
					wc.discardWorkingCopy();
				} catch (JavaModelException e) {
					Logger.getLogger().logError(e);
				}
		}
	}

	public void dispose() {
		IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
			public void run(IProgressMonitor aMonitor) {
				primDispose();
			}
		};
		try {
			if (!WTPCommonPlugin.getWorkspace().isTreeLocked()) {
				WTPCommonPlugin.getWorkspace().run(runnable,null, IWorkspace.AVOID_UPDATE,null);
			} else {
				runnable.run(null);
			}
		} catch (CoreException e) {
			CommonFrameworksPlugin.logError(e);
		}
	}

	public void revert() {
		IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
			public void run(IProgressMonitor aMonitor) {
				primRevert();
			}
		};
		runOperation(runnable, null, true);
	}

	public Set getAffectedFiles() {
		return Collections.EMPTY_SET;
	}

	/**
	 * Insert the method's description here. Creation date: (7/11/2001 6:43:37 PM)
	 * 
	 * @return java.util.HashMap
	 */
	protected HashMap getDeletedCompilationUnits() {
		if (deletedCompilationUnits == null)
			deletedCompilationUnits = new HashMap();
		return deletedCompilationUnits;
	}

	/**
	 * Returns the working copy remembered for the compilation unit encoded in the given editor
	 * input. Does not connect the edit model to the working copy.
	 * 
	 * @param input
	 *            ICompilationUnit
	 * @return the working copy of the compilation unit, or <code>null</code> if the input does
	 *         not encode an editor input, or if there is no remembered working copy for this
	 *         compilation unit
	 */
	public org.eclipse.jdt.core.ICompilationUnit getExistingWorkingCopy(ICompilationUnit cu) throws CoreException {
		ICompilationUnit newCU = getNewCompilationUnitWorkingCopy(cu);
		if (newCU != null)
			return newCU;
		return null;
	}

	/**
	 * Insert the method's description here. Creation date: (7/19/2001 11:00:19 AM)
	 * 
	 * @return java.util.List
	 */
	protected java.util.List getNeedsSavingCompilationUnits() {
		if (needsSavingCompilationUnits == null)
			needsSavingCompilationUnits = new ArrayList();
		return needsSavingCompilationUnits;
	}

	/**
	 * Insert the method's description here. Creation date: (4/26/2001 3:49:05 PM)
	 * 
	 * @return java.util.List
	 */
	protected java.util.List getNewCompilationUnits() {
		if (newCompilationUnits == null)
			newCompilationUnits = new ArrayList();
		return newCompilationUnits;
	}

	/**
	 * It is possible that we have already created this CompilationUnit and its working copy. If
	 * this is the case, return our new working copy and do not create a new one.
	 */
	protected ICompilationUnit getNewCompilationUnitWorkingCopy(ICompilationUnit cu) {
		if (hasNewCompilationUnit(cu)) {
			List list = getNeedsSavingCompilationUnits();
			ICompilationUnit copy;
			for (int i = 0; i < list.size(); i++) {
				copy = (ICompilationUnit) list.get(i);
				if (cu.equals(copy.getPrimary()))
					return copy;
			}
		}
		return null;
	}

	/**
	 * Insert the method's description here. Creation date: (4/26/2001 3:49:05 PM)
	 * 
	 * @return java.util.List
	 */
	protected java.util.List getOriginalNewCompilationUnits() {
		if (originalNewCompilationUnits == null)
			originalNewCompilationUnits = new ArrayList();
		return originalNewCompilationUnits;
	}

	/**
	 * Return the IPackageFragment for the given ICompilationUnit.
	 */
	protected IPackageFragment getPackageFragment(ICompilationUnit cu) {
		if (cu == null)
			return null;
		IJavaElement parent = cu;
		int elementType = cu.getElementType();
		while (parent != null && elementType != IJavaElement.PACKAGE_FRAGMENT) {
			parent = parent.getParent();
			if (parent != null)
				elementType = parent.getElementType();
			else
				elementType = -1;
		}
		return (IPackageFragment) parent;
	}

	protected ISaveHandler getSaveHandler() {
		return SaveHandlerRegister.getSaveHandler();
	}

	/**
	 * Returns the working copy remembered for the compilation unit.
	 * 
	 * @param input
	 *            ICompilationUnit
	 * @return the working copy of the compilation unit, or <code>null</code> if there is no
	 *         remembered working copy for this compilation unit
	 */
	public ICompilationUnit getWorkingCopy(ICompilationUnit cu, boolean forNewCU) throws org.eclipse.core.runtime.CoreException {
		if (cu == null || cu.isWorkingCopy())
			return cu;
		ICompilationUnit newCU = getNewCompilationUnitWorkingCopy(cu);
		if (newCU != null)
			return newCU;
		ICompilationUnit workingCopy = cu.getWorkingCopy(null);
		addNewCompilationUnit(cu, workingCopy);
		return workingCopy;
	}

	/**
	 * Has a new compilation unit already been created.
	 */
	protected boolean hasNewCompilationUnit(ICompilationUnit cu) {
		return getNewCompilationUnits().contains(cu);
	}

	protected boolean isFailedWriteFileFailure(Exception ex) {
		return SaveHandlerHeadless.isFailedWriteFileFailure(ex);
	}

	protected void primAddDeletedCompilationUnit(ICompilationUnit cu) {
		if (cu == null)
			return;
		Object[] info = new Object[2];
		info[0] = getPackageFragment(cu);
		try {
			info[1] = cu.getSource();
		} catch (JavaModelException e) {
			info[1] = null;
		}
		getDeletedCompilationUnits().put(cu, info);
	}

	// This is an internal delete call.
	protected void primDelete(ICompilationUnit cu) {
		try {
			if (cu.exists())
				cu.delete(true, new org.eclipse.core.runtime.NullProgressMonitor());
		} catch (JavaModelException e) {
			org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(e);
			//What to do here?
		}
	}

	protected void primDispose() {
		discardOriginalNewCompilationUnits();
		reviveDeletedCompilationUnits();
		newCompilationUnits = null;
		needsSavingCompilationUnits = null;
		originalNewCompilationUnits = null;
		deletedCompilationUnits = null;
	}

	protected void primRevert() {
		discardOriginalNewCompilationUnits();
		reviveDeletedCompilationUnits();
		newCompilationUnits = null;
		needsSavingCompilationUnits = null;
		originalNewCompilationUnits = null;
		deletedCompilationUnits = null;
	}

	/**
	 * Returns the working copy remembered for the compilation unit encoded in the given editor
	 * input.
	 * 
	 * @param input
	 *            ICompilationUnit
	 * @return the working copy of the compilation unit, or <code>null</code> if the input does
	 *         not encode an editor input, or if there is no remembered working copy for this
	 *         compilation unit
	 */
	protected ICompilationUnit primGetWorkingCopy(ICompilationUnit cu) throws CoreException {
		return null;
	}

	/**
	 * This will save all of the referenced CompilationUnits to be saved.
	 */
	protected void primSaveCompilationUnits(org.eclipse.core.runtime.IProgressMonitor monitor) {
		saveNewCompilationUnits(monitor);
		getDeletedCompilationUnits().clear();
	}

	/**
	 * This will save all of the new CompilationUnits to be saved.
	 */
	protected void primSaveOnlyNewCompilationUnits(org.eclipse.core.runtime.IProgressMonitor monitor) {
		List cus = getNeedsSavingCompilationUnits();
		ICompilationUnit wc;
		for (int i = 0; i < cus.size(); i++) {
			wc = (ICompilationUnit) cus.get(i);
			commitWorkingCopy(wc, monitor);
		}
		cus.clear();
	}

	protected void removeDeletedCompilationUnit(ICompilationUnit cu) {
		if (getDeletedCompilationUnits().remove(cu) != null) {
			if (cu.isWorkingCopy()) {
				ICompilationUnit original, nextCU, testCU;
				original = cu.getPrimary();
				Set cus = getDeletedCompilationUnits().keySet();
				Iterator it = cus.iterator();
				while (it.hasNext()) {
					nextCU = (ICompilationUnit) it.next();
					testCU = nextCU.isWorkingCopy() ? (ICompilationUnit) nextCU.getPrimary() : nextCU;
					if (testCU.equals(original)) {
						cus.remove(nextCU);
						return;
					}
				}
			}
		}
	}

	protected void reviveDeletedCompilationUnit(ICompilationUnit cu, Object[] info, IProgressMonitor pm) {
		if(cu.getJavaProject().isOpen()) {
			if (info[0] != null && info[1] != null) {
				String typeName = cu.getElementName();
				IPackageFragment pack = (IPackageFragment) info[0];
				String source = (String) info[1];
				try {
					ICompilationUnit existingCU = pack.getCompilationUnit(typeName);
					if (existingCU.exists() && getNewCompilationUnits().contains(existingCU))
						existingCU.delete(false, pm);
					pack.createCompilationUnit(typeName, source, false, pm);
				} catch (JavaModelException e) {
					org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(e);
				}
			}
		}
	}

	protected void reviveDeletedCompilationUnits() {
		if (getDeletedCompilationUnits().isEmpty())
			return;
		
		IProgressMonitor pm = new org.eclipse.core.runtime.NullProgressMonitor();
		Iterator it = getDeletedCompilationUnits().entrySet().iterator();
		Map.Entry entry;
		ICompilationUnit cu;
		Object[] info;
		while (it.hasNext()) {
			entry = (Map.Entry) it.next();
			cu = (ICompilationUnit) entry.getKey();
			info = (Object[]) entry.getValue();
			reviveDeletedCompilationUnit(cu, info, pm);
		}

	}

	protected void runOperation(IWorkspaceRunnable aRunnable, IProgressMonitor monitor, boolean validate) {
		primRunOperation(aRunnable, monitor);

		// TODO Break the validator depedency
		//	if (validate)
		//		primRunOperation(aRunnable, monitor);
		//	else {
		//		IProject proj = getValidationProject();
		//			
		//		ValidatorManager mgr = ValidatorManager.getManager();
		//		boolean disableValidators = proj != null;
		//		boolean wasSuspended = false;
		//		if (disableValidators) {
		//			wasSuspended = mgr.isSuspended(proj);
		//			if (!wasSuspended)
		//				mgr.suspendValidation(proj, true);
		//		}
		//		try {
		//			primRunOperation(aRunnable, monitor);
		//		} finally {
		//			if (disableValidators && !wasSuspended)
		//				mgr.suspendValidation(proj, false);
		//		}
		//	}
	}

	protected void primRunOperation(IWorkspaceRunnable aRunnable, IProgressMonitor monitor) {
		
		if (aRunnable != null) {
			//if (workspace.isTreeLocked())
			//Logger.getLogger().logTrace(ResourceHandler.getString("Cannot_run_J2EEUIWorkingCo_ERROR_"));
			// //$NON-NLS-1$ = "Cannot run J2EEUIWorkingCopyManager operation because the Workspace
			// tree is locked."
			//else {
			if (!WTPCommonPlugin.getWorkspace().isTreeLocked()) {
				try {
					WTPCommonPlugin.getWorkspace().run(aRunnable, monitor);
				} catch (CoreException e) {
					throw new SaveFailedException(e);
				}
			}
		}
	}

	/**
	 * This will save all of the referenced CompilationUnits to be saved.
	 */
	public void saveCompilationUnits(org.eclipse.core.runtime.IProgressMonitor monitor) {
		getSaveHandler().access();
		try {
			IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
				public void run(IProgressMonitor aMonitor) {
					primSaveCompilationUnits(aMonitor);
				}
			};
			runOperation(runnable, monitor, true);
		} catch (SaveFailedException ex) {
			getSaveHandler().handleSaveFailed(ex, monitor);
		} finally {
			getSaveHandler().release();
		}
	}

	/**
	 * This will save all of the referenced CompilationUnits to be saved.
	 */
	protected void saveNewCompilationUnits(IProgressMonitor monitor) {
		primSaveOnlyNewCompilationUnits(monitor);
		getOriginalNewCompilationUnits().clear();
		getNewCompilationUnits().clear();
	}

	/**
	 * This will save all of the new CompilationUnits to be saved.
	 */
	public void saveOnlyNewCompilationUnits(org.eclipse.core.runtime.IProgressMonitor monitor) {
		getSaveHandler().access();
		try {
			IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
				public void run(IProgressMonitor aMonitor) {
					primSaveOnlyNewCompilationUnits(aMonitor);
				}
			};
			runOperation(runnable, monitor, false);
		} catch (SaveFailedException ex) {
			getSaveHandler().handleSaveFailed(ex, monitor);
		} finally {
			getSaveHandler().release();
		}
	}

	protected boolean shouldSaveReadOnly(ICompilationUnit wc) {
		IResource resource = null;

		resource = (IResource) wc.getPrimary().getAdapter(IRESOURCE_CLASS);

		if (resource == null || resource.getType() != IResource.FILE || !resource.getResourceAttributes().isReadOnly())
			return false;

		return getSaveHandler().shouldContinueAndMakeFileEditable((IFile) resource);
	}

	/**
	 * @see com.ibm.etools.j2ee.workbench.IJ2EEWorkingCopyManager#hasWorkingCopies()
	 */
	public boolean hasWorkingCopies() {
		return (deletedCompilationUnits != null && !deletedCompilationUnits.isEmpty()) || (needsSavingCompilationUnits != null && !needsSavingCompilationUnits.isEmpty()) || (newCompilationUnits != null && !newCompilationUnits.isEmpty());
	}

}
