package org.eclipse.jst.j2ee.emf2xml.sed;


import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapter;
import org.eclipse.wst.common.internal.emf.resource.EMF2DOMRenderer;
import org.eclipse.wst.common.internal.emf.resource.TranslatorResource;
import org.eclipse.wst.common.internal.emf.utilities.DOMUtilities;
import org.eclipse.wst.common.internal.emfworkbench.WorkbenchResourceHelper;
import org.eclipse.wst.common.internal.emfworkbench.integration.ResourceSetWorkbenchEditSynchronizer;
import org.eclipse.wst.sse.core.IModelLifecycleListener;
import org.eclipse.wst.sse.core.IModelManager;
import org.eclipse.wst.sse.core.IModelStateListener;
import org.eclipse.wst.sse.core.IStructuredModel;
import org.eclipse.wst.sse.core.ModelLifecycleEvent;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.xml.core.document.XMLModel;
import org.eclipse.wst.xml.core.document.XMLNode;
import org.eclipse.wst.xml.core.internal.document.DocumentTypeImpl;
import org.w3c.dom.Node;

import com.ibm.wtp.common.logger.proxy.Logger;
import com.ibm.wtp.emf.workbench.ProjectResourceSet;

public class EMF2DOMSedRenderer extends EMF2DOMRenderer implements IModelStateListener, IModelLifecycleListener {

	/** The XML DOM model */
	protected XMLModel xmlModel;

	/** Used internally; the unique id for the xml model */
	protected String xmlModelId;

	private IModelManager modelManager;

	protected Object aboutToChangeNode = null;

	protected boolean xmlModelReverted = false;

	protected boolean isBatchChanges = false;

	private boolean isSaving = false;

	public EMF2DOMSedRenderer() {
		super();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.etools.emf2xml.impl.EMF2DOMRenderer#managesDOMAdapters()
	 */
	protected boolean managesDOMAdapters() {
		return false;
	}

	protected EMF2DOMAdapter createRootDOMAdapter() {
		return new EMF2DOMSedAdapter(getResource(), document, this, getResource().getRootTranslator());
	}

	public void deRegisterAsModelStateListener() {
		if (xmlModel != null)
			xmlModel.removeModelStateListener(this);
	}

	public void deRegisterAsModelLifecycleListener() {
		if (xmlModel != null)
			xmlModel.removeModelLifecycleListener(this);
	}

	/**
	 * Return the DOM model for this resource.
	 */
	public XMLModel getXMLModel() {
		return xmlModel;
	}

	public String getXMLModelId() {
		return xmlModelId;
	}

	public boolean isModified() {
		return (getXMLModel() != null && getXMLModel().isDirty());
	}

	public void modelAboutToBeChanged(IStructuredModel model) {
		if (model.getStructuredDocument() != null)
			aboutToChangeNode = model.getStructuredDocument().getFirstStructuredDocumentRegion();
	}

	public void modelChanged(IStructuredModel model) {
		if (isBatchChanges)
			return;
		try {
			if (aboutToChangeNode != null && model.getStructuredDocument() != null && model.getStructuredDocument().getFirstStructuredDocumentRegion() != aboutToChangeNode) {
				modelAccessForWrite();
				try {
					xmlModelReverted = true;
					resource.unload();
				} finally {
					if (getXMLModel() != null)
						getXMLModel().releaseFromEdit();
				}
			}
		} finally {
			aboutToChangeNode = null;
		}
	}

	public void accessForRead() {
		if (!resource.isNew()) {
			String id = getModelManagerId();
			getModelManager().getExistingModelForRead(id);
		}
	}

	public void accessForWrite() {
		modelAccessForWrite();
	}

	private void modelAccessForWrite() {
		String id = getModelManagerId();
		getModelManager().getExistingModelForEdit(id);
	}

	public void modelDirtyStateChanged(IStructuredModel model, boolean isDirty) {
		if (!isDirty && resource.isModified()) { //The XMLModel was saved
			resource.setModified(false);
			long stamp = WorkbenchResourceHelper.computeModificationStamp(resource);
			WorkbenchResourceHelper.setSynhronizationStamp(resource, stamp);
		}
	}

	public void modelResourceDeleted(IStructuredModel model) {
		//Do nothing
	}

	public void modelResourceMoved(IStructuredModel oldModel, IStructuredModel newModel) {
		//Do nothing
	}

	/**
	 * This method is called just prior to being removed from the ResourceSet. Ensure that all
	 * reference counts to the XMLModel are removed.
	 */
	public void preDelete() {
		if (resource.isLoaded())
			deregisterFromXMLModel();
	}

	public void preUnload() {
		deregisterFromXMLModel();
	}

	private void deregisterFromXMLModel() {
		deRegisterAsModelStateListener();
		deRegisterAsModelLifecycleListener();
		// This try/catch block is a hack to fix defect 204114. This occurs
		// because
		// the model manager plugin is shut down and unloaded before the j2ee
		// plugin.
		// Calling getModelManager() can result in a class cast exception that
		// should
		// be ignored.
		//ModelManager mgr = null;
		try {
			getModelManager();
		} catch (ClassCastException exc) {
			return;
		}
		if (xmlModel != null) {
			int writeCount = resource.getWriteCount();
			int readCount = resource.getReadCount();
			for (int i = 0; i < writeCount; i++)
				xmlModel.releaseFromEdit();
			for (int ii = 0; ii < readCount; ii++)
				xmlModel.releaseFromRead();
		}
		EMF2DOMAdapter adapter = (EMF2DOMAdapter) EcoreUtil.getAdapter(resource.eAdapters(), EMF2DOMAdapter.ADAPTER_CLASS);
		if (adapter != null) {
			adapter.removeAdapters(adapter.getNode());
		}
		xmlModel = null;
		xmlModelId = null;
	}

	/**
	 * Insert the method's description here. Creation date: (9/7/2001 10:49:53 AM)
	 */
	public void registerAsModelStateListener() {
		this.xmlModel.addModelStateListener(this);
	}

	public void registerAsModelLifecycleListener() {
		this.xmlModel.addModelLifecycleListener(this);
	}

	/**
	 * Return the DOM model for this resource.
	 */
	public void setXMLModel(XMLModel xmlModel) {
		deRegisterAsModelStateListener();
		deRegisterAsModelLifecycleListener();
		this.xmlModel = xmlModel;
		registerAsModelStateListener();
		registerAsModelLifecycleListener();
	}

	public void setXMLModelId(String id) {
		xmlModelId = id;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.etools.emf2xml.Renderer#doSave(java.io.OutputStream, java.util.Map)
	 */
	public void doSave(OutputStream outputStream, Map options) throws IOException {

		try {
			isSaving = true;
			if (null != outputStream) {
				throw new RuntimeException(UIResourceHandler.getString("EMF2DOMSedRenderer_UI_0", new Object[]{this.getClass().getName()}));} //$NON-NLS-1$
			createDOMTreeIfNecessary();
			ResourceSetWorkbenchEditSynchronizer synchronizer = (ResourceSetWorkbenchEditSynchronizer) ((ProjectResourceSet) resource.getResourceSet()).getSynchronizer();
			IFile aFile = WorkbenchResourceHelper.getFile(resource);
			try {
				synchronizer.preSave(aFile);
				xmlModel.save(aFile);
			} catch (CoreException ex) {
				synchronizer.removeFromRecentlySavedList(aFile);
				Logger.getLogger().logError(ex);
			}
			cacheSynchronizationStamp();
		} finally {
			isSaving = false;
		}
	}

	/**
	 * @see com.ibm.etools.common.mof2dom.XMLDOMResource#wasReverted()
	 */
	public boolean wasReverted() {
		return xmlModelReverted;
	}

	protected IModelManager getModelManager() {
		if (modelManager == null)
			modelManager = StructuredModelManager.getModelManager();
		return modelManager;
	}

	/**
	 * Return id used to key the XML resource in the XML ModelManager.
	 */
	protected String getModelManagerId() {
		if (xmlModelId == null) {
			IFile file = WorkbenchResourceHelper.getFile(getResource());
			if (file != null) {
				xmlModelId = getModelManager().calculateId(file);
			} else {
				xmlModelId = resource.getURI() + Long.toString(System.currentTimeMillis());
			}
		}
		return xmlModelId;
	}

	public void releaseFromRead() {
		if (xmlModel != null)
			xmlModel.releaseFromRead();
	}

	public void releaseFromWrite() {
		if (xmlModel != null)
			xmlModel.releaseFromEdit();
	}

	protected ResourceSet getResourceSet() {
		return resource == null ? null : resource.getResourceSet();
	}

	public boolean isShared() {
		if (getResourceSet() == null || xmlModel == null)
			return false;
		return xmlModel.isShared();
	}

	public boolean isSharedForWrite() {
		if (getResourceSet() == null || xmlModel == null)
			return false;
		return xmlModel.isSharedForEdit();
	}

	/**
	 * Create a new Document given
	 * 
	 * @aResource.
	 */
	protected void createDocument() {
		TranslatorResource res = getResource();
		res.setDefaults();
		IFile file = WorkbenchResourceHelper.getFile(resource);
		InputStream is = DOMUtilities.createHeaderInputStream(res.getDoctype(), res.getPublicId(), res.getSystemId());
		if (is == null)
			return;
		try {
			try {
				List folders = new ArrayList();
				IContainer container = file.getParent();
				while (null != container && !container.exists() && container instanceof IFolder) {
					folders.add(container);
					container = container.getParent();
				}
				IFolder folder = null;
				for (int i = 0; i < folders.size(); i++) {
					folder = (IFolder) folders.get(i);
					folder.create(true, true, null);
				}
				file.create(is, true, null);
				file.setLocal(true, 1, null);
			} catch (CoreException e1) {
				com.ibm.wtp.common.logger.proxy.Logger.getLogger().logError(e1);
			} finally {
				if (null != is) {
					is.close();
				}
			}
			initializeXMLModel(file, true);
		} catch (java.io.IOException ex) {
			com.ibm.wtp.common.logger.proxy.Logger.getLogger().logError(UIResourceHandler.getString("Unexpected_IO_exception_occurred_creating_xml_document_1_EXC_"));//$NON-NLS-1$
			com.ibm.wtp.common.logger.proxy.Logger.getLogger().logError(ex);
		}
	}

	protected void createDOMTreeIfNecessary() {
		if (needsToCreateDOM)
			createDOMTree();
	}

	private XMLModel initializeXMLModel(IFile file, boolean forWrite) throws UnsupportedEncodingException, IOException {
		if (file == null || !file.exists())
			throw new FileNotFoundException((file == null) ? "null" : file.getFullPath().toOSString()); //$NON-NLS-1$
		String id = getModelManagerId();
		try {
			if (forWrite)
				setXMLModel((XMLModel) getModelManager().getModelForEdit(file));
			else
				setXMLModel((XMLModel) getModelManager().getModelForRead(file));
			needsToCreateDOM = false;
		} catch (CoreException e) {
			com.ibm.wtp.common.logger.proxy.Logger.getLogger().logError(e);
			return null;
		}
		syncReferenceCounts(id, forWrite);
		if (xmlModel != null) {
			xmlModel.setModelManager(getModelManager());
			xmlModel.setBaseLocation(id);
		}
		if (xmlModel != null)
			document = xmlModel.getDocument();
		return xmlModel;
	}

	private void syncReferenceCounts(String id, boolean forWrite) {
		int editIndex = 0, readIndex = 0;
		if (forWrite)
			editIndex++;
		else
			readIndex++;
		int writeCount = resource.getWriteCount();
		int readCount = resource.getReadCount();
		for (int i = writeCount; i > editIndex; i--)
			modelManager.getExistingModelForEdit(id);
		for (int i = readCount; i > readIndex; i--)
			modelManager.getExistingModelForRead(id);
	}

	protected void loadDocument(InputStream in, Map options) throws IOException {
		if (null != in) {
			throw new RuntimeException(UIResourceHandler.getString("EMF2DOMSedRenderer_UI_1", new Object[]{this.getClass().getName()}));} //$NON-NLS-1$
		IFile file = WorkbenchResourceHelper.getFile(resource);
		initializeXMLModel(file, (resource.getWriteCount() != 0));
		cacheSynchronizationStamp();
	}

	private void cacheSynchronizationStamp() {
		IFile file = WorkbenchResourceHelper.getFile(resource);
		if (file != null) {
			if (xmlModel != null)
				xmlModel.resetSynchronizationStamp(file);
		}
	}

	public void setBatchMode(boolean isBatch) {
		if (isBatch) {
			isBatchChanges = true;
			getXMLModel().aboutToChangeModel();
		} else {
			setRootNodeAdapterNotificationEnabled(false);
			try {
				getXMLModel().changedModel();
			} finally {
				setRootNodeAdapterNotificationEnabled(true);
			}
			isBatchChanges = false;
		}
	}

	private void setRootNodeAdapterNotificationEnabled(boolean b) {
		EObject root = resource.getRootObject();
		if (root != null) {
			EMF2DOMAdapter adapter = (EMF2DOMAdapter) EcoreUtil.getExistingAdapter(root, EMF2DOMAdapter.ADAPTER_CLASS);
			if (adapter != null)
				adapter.setNotificationEnabled(b);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.etools.emf2xml.impl.EMF2DOMRenderer#getExistingDOMAdapter(org.w3c.dom.Node)
	 */
	public EMF2DOMAdapter getExistingDOMAdapter(Node node) {
		XMLNode xNode = (XMLNode) node;
		return (EMF2DOMSedAdapter) xNode.getAdapterFor(EMF2DOMAdapter.ADAPTER_CLASS);
	}

	public void removeDOMAdapter(Node aNode, EMF2DOMAdapter anAdapter) {
		((XMLNode) aNode).removeAdapter((EMF2DOMSedAdapter) anAdapter);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.wtp.internal.emf.xml.EMF2DOMRenderer#replaceDocumentType(java.lang.String,
	 *      java.lang.String, java.lang.String)
	 */
	public void replaceDocumentType(String docTypeName, String publicId, String systemId) {
		if (document == null)
			return;
		DocumentTypeImpl docType = (DocumentTypeImpl) document.getDoctype();
		if (docType == null)
			return;
		if (publicId == null && systemId == null)
			document.removeChild(docType);
		else {
			docType.setPublicId(publicId);
			docType.setSystemId(systemId);
		}
	}

	public boolean useStreamsForIO() {
		return false;
	}

	public void processPostModelEvent(ModelLifecycleEvent event) {
		// TODO Auto-generated method stub

	}

	public void processPreModelEvent(ModelLifecycleEvent event) {
		if (!isSaving) {
			if (event.getType() == ModelLifecycleEvent.MODEL_SAVED) {
				ResourceSetWorkbenchEditSynchronizer synchronizer = (ResourceSetWorkbenchEditSynchronizer) ((ProjectResourceSet) resource.getResourceSet()).getSynchronizer();
				IFile aFile = WorkbenchResourceHelper.getFile(resource);
				synchronizer.preSave(aFile);
			}
		}
	}
}