package org.eclipse.cdt.internal.ui.editor;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.IBuffer;
import org.eclipse.cdt.core.model.IOpenable;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.internal.core.model.IBufferFactory;
import org.eclipse.cdt.internal.core.model.IWorkingCopy;
import org.eclipse.cdt.internal.ui.CStatusConstants;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.IEditorInputDelegate;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.AbstractDocument;
import org.eclipse.jface.text.DefaultLineTracker;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.GapTextStore;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.editors.text.FileDocumentProvider;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel;

public class CDocumentProvider extends FileDocumentProvider {

	/**
	 * Bundle of all required informations to allow working copy management. 
	 */
	protected class CDocument extends AbstractDocument {
		
		/**
		 * Creates a new empty document.
		 */
		public CDocument() {
			super();
			setTextStore(new GapTextStore(50, 300));
			setLineTracker(new DefaultLineTracker());
			completeInitialization();
		}
		
		/**
		 * Creates a new document with the given initial content.
		 *
		 * @param initialContent the document's initial content
		 */
		public CDocument(String initialContent) {
			super();
			setTextStore(new GapTextStore(50, 300));
			setLineTracker(new DefaultLineTracker());	
			getStore().set(initialContent);
			getTracker().set(initialContent);
			completeInitialization();
		}
	};
	
	/**
	 * Bundle of all required informations to allow working copy management. 
	 */
	protected class TranslationUnitFileInfo extends FileInfo {
			
		IWorkingCopy fCopy;
			
		TranslationUnitFileInfo(IDocument document, IAnnotationModel model, FileSynchronizer fileSynchronizer, IWorkingCopy copy) {
			super(document, model, fileSynchronizer);
			fCopy= copy;
		}
			
		void setModificationStamp(long timeStamp) {
			fModificationStamp= timeStamp;
		}
	};
	/**
	 * Creates <code>IBuffer</code>s based on documents.
	 */
	protected class BufferFactory implements IBufferFactory {
			
		private IDocument internalGetDocument(IFileEditorInput input) throws CoreException {
			IDocument document= getDocument(input);
			if (document != null)
				return document;
			return CDocumentProvider.this.createDocument(input);
		}
			
		public IBuffer createBuffer(IOpenable owner) {
			if (owner instanceof IWorkingCopy) {
						
				IWorkingCopy unit= (IWorkingCopy) owner;
				ITranslationUnit original= (ITranslationUnit) unit.getOriginalElement();
				IResource resource= original.getResource();
				if (resource instanceof IFile) {
					IFileEditorInput providerKey= new FileEditorInput((IFile) resource);
						
					IDocument document= null;
					IStatus status= null;
						
					try {
						document= internalGetDocument(providerKey);
					} catch (CoreException x) {
						status= x.getStatus();
						document= new Document();
						initializeDocument(document);
					}
							
					DocumentAdapter adapter= new DocumentAdapter(unit, document, new DefaultLineTracker(), CDocumentProvider.this, providerKey);
					adapter.setStatus(status);
					return adapter;
				}
							
			}
			return DocumentAdapter.NULL;
		}
	};


	/** The buffer factory */
	private IBufferFactory fBufferFactory= new BufferFactory();
	/** Indicates whether the save has been initialized by this provider */
	private boolean fIsAboutToSave= false;

	/**
	 * @see AbstractDocumentProvider#createDocument(Object)
	 */ 
	protected IDocument createDocument(Object element) throws CoreException {
		IDocument document = null;
		IStorage storage = null;

		if (element instanceof IEditorInputDelegate) {
			if (((IEditorInputDelegate) element).getDelegate() != null)
				return createDocument(((IEditorInputDelegate) element).getDelegate());
			else
				storage = ((IEditorInputDelegate) element).getStorage();
		}
			
		if (element instanceof IStorageEditorInput)
			storage= ((IStorageEditorInput) element).getStorage();
		
		if ( storage != null ) {
			document = new CDocument();
			setDocumentContent(document, storage.getContents(), getDefaultEncoding());
		}

		//IDocument document= super.createDocument(element);
		initializeDocument(document);
		return document;
	}
	
	/*
	 * @see AbstractDocumentProvider#createAnnotationModel(Object)
	 */
	protected IAnnotationModel createAnnotationModel(Object element) throws CoreException {
		if ( element instanceof IEditorInputDelegate && ((IEditorInputDelegate)element).getDelegate() != null )
			return createAnnotationModel( ((IEditorInputDelegate)element).getDelegate() );
		if (element instanceof IFileEditorInput) {
			IFileEditorInput input= (IFileEditorInput) element;
			return new CMarkerAnnotationModel(input.getFile());
		} else if (element instanceof IStorageEditorInput) {
			// Fall back on the adapter.
			IStorageEditorInput input = (IStorageEditorInput) element;
			IResource res = (IResource)input.getAdapter(IResource.class);
			if (res != null && res.exists()) {
				return new CMarkerAnnotationModel(res);
			}
		}
		
		return super.createAnnotationModel(element);
	}
	
	/*
	 * @see AbstractDocumentProvider#createElementInfo(Object)
	 */
	protected ElementInfo createElementInfo(Object element) throws CoreException {
		if ( !(element instanceof IFileEditorInput))
			return super.createElementInfo(element);
			
		IFileEditorInput input= (IFileEditorInput) element;
		ITranslationUnit original= createTranslationUnit(input.getFile());
		if (original != null) {
				
			try {
								
				try {
					refreshFile(input.getFile());
				} catch (CoreException x) {
					handleCoreException(x, CEditorMessages.getString("TranslationUnitDocumentProvider.error.createElementInfo")); //$NON-NLS-1$
				}
				
				IAnnotationModel m= createAnnotationModel(input);
				IBufferFactory factory = getBufferFactory();
				IWorkingCopy c= (IWorkingCopy) original.getSharedWorkingCopy(getProgressMonitor(), factory);
				
				DocumentAdapter a= null;
				try {
					a= (DocumentAdapter) c.getBuffer();
				} catch (ClassCastException x) {
					IStatus status= new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, CStatusConstants.TEMPLATE_IO_EXCEPTION, "Shared working copy has wrong buffer", x); //$NON-NLS-1$
					throw new CoreException(status);
				}
				
				FileSynchronizer f= new FileSynchronizer(input); 
				f.install();
				
				TranslationUnitFileInfo info= new TranslationUnitFileInfo(a.getDocument(), m, f, c);
				info.setModificationStamp(computeModificationStamp(input.getFile()));
				info.fStatus= a.getStatus();
				info.fEncoding= getPersistedEncoding(input);
								
				return info;
				
			} catch (CModelException x) {
				throw new CoreException(x.getStatus());
			}
		} else {		
			return super.createElementInfo(element);
		}
	}
	/*
	 * Creates a translation unit using the core model
	 */
	protected ITranslationUnit createTranslationUnit(IFile file) {
		Object element= CoreModel.getDefault().create(file);
		if (element instanceof ITranslationUnit)
			return (ITranslationUnit) element;
		return null;
	}
	/*
	 * @see AbstractDocumentProvider#disposeElementInfo(Object, ElementInfo)
	 */
	protected void disposeElementInfo(Object element, ElementInfo info) {
		
		if (info instanceof TranslationUnitFileInfo) {
			TranslationUnitFileInfo cuInfo= (TranslationUnitFileInfo) info;
			cuInfo.fCopy.destroy();
		}
		
		super.disposeElementInfo(element, info);
	}

	/*
	 * @see AbstractDocumentProvider#doSaveDocument(IProgressMonitor, Object, IDocument, boolean)
	 */
	protected void doSaveDocument(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException {

		ElementInfo elementInfo= getElementInfo(element);		
		if (elementInfo instanceof TranslationUnitFileInfo) {
			TranslationUnitFileInfo info= (TranslationUnitFileInfo) elementInfo;
			
			// update structure, assumes lock on info.fCopy
			info.fCopy.reconcile();
			
			ITranslationUnit original= (ITranslationUnit) info.fCopy.getOriginalElement();
			IResource resource= original.getResource();
			
			if (resource == null) {
				// underlying resource has been deleted, just recreate file, ignore the rest
				super.doSaveDocument(monitor, element, document, overwrite);
				return;
			}
			
			if (resource != null && !overwrite)
				checkSynchronizationState(info.fModificationStamp, resource);
				
//			if (fSavePolicy != null)
//				fSavePolicy.preSave(info.fCopy);
			
			// inform about the upcoming content change
			fireElementStateChanging(element);	
			try {
				fIsAboutToSave= true;
				// commit working copy
				info.fCopy.commit(overwrite, monitor);
			} catch (CoreException x) {
				// inform about the failure
				fireElementStateChangeFailed(element);
				throw x;
			} catch (RuntimeException x) {
				// inform about the failure
				fireElementStateChangeFailed(element);
				throw x;
			} finally {
				fIsAboutToSave= false;
			}
			
			// If here, the dirty state of the editor will change to "not dirty".
			// Thus, the state changing flag will be reset.
			
			AbstractMarkerAnnotationModel model= (AbstractMarkerAnnotationModel) info.fModel;
			model.updateMarkers(info.fDocument);
			
			if (resource != null)
				info.setModificationStamp(computeModificationStamp(resource));
				
//			if (fSavePolicy != null) {
//				ICompilationUnit unit= fSavePolicy.postSave(original);
//				if (unit != null) {
//					IResource r= unit.getResource();
//					IMarker[] markers= r.findMarkers(IMarker.MARKER, true, IResource.DEPTH_ZERO);
//					if (markers != null && markers.length > 0) {
//						for (int i= 0; i < markers.length; i++)
//							model.updateMarker(markers[i], info.fDocument, null);
//					}
//				}
//			}
				
			
		} else {
			super.doSaveDocument(monitor, element, document, overwrite);
		}		
	}

	/**
	 * Gets the BufferFactory.
	 */
	public IBufferFactory getBufferFactory() {
		return fBufferFactory;
	}

	/**
	 * Returns the underlying resource for the given element.
	 * 
	 * @param the element
	 * @return the underlying resource of the given element
	 */
	public IResource getUnderlyingResource(Object element) {
		if (element instanceof IFileEditorInput) {
			IFileEditorInput input= (IFileEditorInput) element;
			return input.getFile();
		}
		return null;
	}

	public IWorkingCopy getWorkingCopy(IEditorInput element) {
		
		ElementInfo elementInfo= getElementInfo(element);		
		if (elementInfo instanceof TranslationUnitFileInfo) {
			TranslationUnitFileInfo info= (TranslationUnitFileInfo) elementInfo;
			return info.fCopy;
		}
		return null;
	}

	protected void initializeDocument(IDocument document) {
		if (document != null) {
			IDocumentPartitioner partitioner= CUIPlugin.getDefault().getTextTools().createDocumentPartitioner();
			partitioner.connect(document);
			document.setDocumentPartitioner(partitioner);
		}
	}
	/**
	 * Saves the content of the given document to the given element.
	 * This is only performed when this provider initiated the save.
	 * 
	 * @param monitor the progress monitor
	 * @param element the element to which to save
	 * @param document the document to save
	 * @param overwrite <code>true</code> if the save should be enforced
	 */
	public void saveDocumentContent(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException {
		
		if (!fIsAboutToSave)
			return;
		
		if (element instanceof IFileEditorInput) {
			IFileEditorInput input= (IFileEditorInput) element;
			try {
				String encoding= getEncoding(element);
				if (encoding == null)
					encoding= ResourcesPlugin.getEncoding();
				InputStream stream= new ByteArrayInputStream(document.get().getBytes(encoding));
				IFile file= input.getFile();
				file.setContents(stream, overwrite, true, monitor);
			} catch (IOException x)  {
				IStatus s= new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, IStatus.OK, x.getMessage(), x);
				throw new CoreException(s);
			}
		}
	}

	/**
	 * 
	 */
	public void shutdown() {
		// TODO Auto-generated method stub	
	}

	/**
	 * @param input
	 * @return
	 */
	public boolean isConnected(IEditorInput input) {
		return getElementInfo(input) != null;
	}
	
	/**
	 * @see org.eclipse.ui.texteditor.IDocumentProviderExtension#getStatus(Object)
	 */
	public IStatus getStatus(Object element) {
		if (element instanceof IEditorInputDelegate) {
			if (((IEditorInputDelegate) element).getDelegate() != null)
				return super.getStatus(((IEditorInputDelegate) element).getDelegate());
			else
				return new Status(IStatus.INFO,CUIPlugin.getPluginId(),0,"",null);
		}
		return super.getStatus(element);
	}
}
