/*******************************************************************************
 * Copyright (c) 2008, 2011 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.compare.internal.win32;

import java.io.File;
import java.util.Vector;

import org.eclipse.jface.action.IMenuManager;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.ole.win32.Variant;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchWindow;

/**
 * Class that manages a Word document comparison using OLE.
 */
public class WordComparison {

	private final OleFrame frame;
	private OleClientSite site;
	private boolean inplace;
	private OleAutomation document;
	
	public WordComparison(Composite composite) {
		frame = new OleFrame(composite, SWT.NONE);
	}

	// These helper methods facilitate writing the OLE apps
	private static Variant invoke(OleAutomation auto, String command) {
		return auto.invoke(property(auto, command), new Variant[0]);
	}

	private static Variant invoke(OleAutomation auto, OleAutomation reference, String command) {
		return auto.invoke(property(auto, reference, command), new Variant[0]);
	}

	private static Variant invoke(OleAutomation auto, OleAutomation reference, String command, String value) {
		return auto.invoke(property(auto, reference, command), new Variant[] { new Variant(value) });
	}

	private static Variant invoke(OleAutomation auto, String command, int value) {
		return auto.invoke(property(auto, command), new Variant[] { new Variant(value) });
	}

	private static Variant invoke(OleAutomation auto, String command, String value) {
		return auto.invoke(property(auto, command), new Variant[] { new Variant(value) });
	}

	private static Variant getVariantProperty(OleAutomation auto, String name) {
		Variant varResult = auto.getProperty(property(auto, name));
		if (varResult != null && varResult.getType() != OLE.VT_EMPTY) {
			return varResult;
		}
		throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_0, name));
	}

	private static OleAutomation getAutomationProperty(OleAutomation auto, String name) {
		Variant varResult = getVariantProperty(auto, name);
		try {
			OleAutomation automation = varResult.getAutomation();
			if (automation != null)
				return automation;
		} finally {
			varResult.dispose();
		}
		throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_1, name));
	}
	
	private static OleAutomation getAutomationResult(OleAutomation auto, String command, int value) {
		Variant varResult = invoke(auto, command, value);
		if (varResult != null) {
			try {
				OleAutomation result = varResult.getAutomation();
				if (result != null)
					return result;
			} finally {
				varResult.dispose();
			}
		}
		throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_2, command, Integer.toString(value)));
	}
	
	private static OleAutomation getAutomationResult(OleAutomation auto, String command, String value) {
		Variant varResult = invoke(auto, command, value);
		if (varResult != null) {
			try {
				OleAutomation result = varResult.getAutomation();
				if (result != null)
					return result;
			} finally {
				varResult.dispose();
			}
		}
		throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_3, command, value));
	}


	/**
	 * <p>This methods workarounds the feature in doc documents. Some properties are not accessible
	 * using names when a diff document is created. The workaround is to obtain the id of the
	 * method from an original document and use it in the newly created one.</p>
	 *
	 * <p>An exception is thrown if the id cannot be retrieved</p>
	 *
	 * Reference information for id assignment: <a href="
	 * http://msdn.microsoft.com/en-us/library/w7a36sdf%28VS.80%29.aspx">http://msdn.microsoft.com/en-us/library/w7a36sdf%28VS.80%29.aspx</a>
	 *
	 * @param auto - object from which we want to get the property, must not be <code>null</code>
	 * @param reference - an reference object from which the property will be obtained.
	 * @param name - the name of the property, must not be <code>null</code>
	 */
	private static int property(OleAutomation auto, OleAutomation reference, String name) {
		int[] ids = auto.getIDsOfNames(new String[] { name });
		if (ids != null) {
			return ids[0];
		}
		if(reference == null) throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_4, name)) ;

		// the property was not retrieved at that point, try to get it from the reference object
		ids = reference.getIDsOfNames(new String[] { name });
		if (ids == null) {
			throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_4, name));
		}
		return ids[0];
	}

	private static int property(OleAutomation auto, String name) {
		int[] ids = auto.getIDsOfNames(new String[] { name });
		if (ids == null) throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_4, name));
		return ids[0];
	}

	private static boolean setProperty(OleAutomation auto, String name, boolean value) {
		return auto.setProperty(property(auto, name), new Variant(value));
	}

	/**
	 * Open the file at the given path as a document in Word.
	 * 
	 * @param filePath
	 *            the path of the file containing the document
	 * @param inplace
	 *            whether Word is to be opened in-place or in a separate window
	 * @throws SWTException
	 *             if the document could not be opened for some reason
	 */
	public void openDocument(String filePath, boolean inplace) throws SWTException {
		resetSite(inplace ? filePath : null);
		if (inplace) {
			site.doVerb(OLE.OLEIVERB_SHOW);
		} else {
			OleAutomation application = createApplication();
			try {
				// Track the external document we just opened
				document = openDocument(application, filePath);
				setDocumentVisible(document, true);
			} finally {
				application.dispose();
			}
		}
	}

	/**
	 * Compares the base document with the revised document and saves the
	 * comparison in the working copy which can then be opened using
	 * openDocument.
	 * 
	 * @param baseDocument
	 *            the base document
	 * @param revisedDocument
	 *            the revised document
	 * @param workingCopy
	 *            the working copy (will be overwritten)
	 * @throws SWTException
	 *             if an SWT error occurs
	 */
	public void createWorkingCopy(String baseDocument, String revisedDocument, String workingCopy) throws SWTException {
		resetSite(null);
		OleAutomation application = createApplication();
		try {
			OleAutomation document = openDocument(application, revisedDocument);
			try {
				setDocumentVisible(document,false);
				compareDocument(document, baseDocument, revisedDocument);
				OleAutomation activeDocument = getActiveDocument(application);
				try {
					Variant varResult = invoke(activeDocument, document, "SaveAs", workingCopy); //$NON-NLS-1$
					if (varResult == null)
						throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_6, workingCopy));
					varResult.dispose();
				} finally {
					closeDocument(activeDocument, document);
				}
			} finally {
				closeDocument(document, null);
			}
		} finally {
			try {
				//Quit application without saving any changes
				int [] ids = application.getIDsOfNames(new String [] {"Quit", "SaveChanges"});
				final Variant wdDoNotSaveChanges = new Variant(0);
				Variant varResult = application.invoke(ids[0], new Variant[]{ wdDoNotSaveChanges }, new int[] {ids[1]});
				if (varResult != null) {
					varResult.dispose();
				}
			} catch (SWTException e) {
				// We don't want to throw the exception as we may mask another exception
				Activator.log(e);
			} finally {
				application.dispose();
			}
		}
	}
	
	private void closeDocument(OleAutomation document, OleAutomation reference) {
		// Close the first document: destination.Close()
		try {
			Variant varResult = invoke(document, reference, "Close"); //$NON-NLS-1$
			if (varResult != null) {
				varResult.dispose();
			}
		} catch (SWTException e) {
			// We don't want to throw the exception as we may mask another
			// exception
			Activator.log(e);
		} finally {
			document.dispose();
		}
	}

	private void compareDocument(OleAutomation document, String baseDocument, String revisedDocument) {
		// Compare to the second document: compare = destination.Compare(p1)
		Variant varResult = invoke(document, "Compare", baseDocument); //$NON-NLS-1$
		if (varResult == null)
			throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_9, baseDocument, revisedDocument));
		varResult.dispose();
	}
	
	private boolean getDocumentDirty(OleAutomation document) {
		// 		word.document.Saved
		if (document != null) {
			Variant variantProperty = getVariantProperty(document, "Saved"); //$NON-NLS-1$
			if (variantProperty != null) {
				try {
					return !variantProperty.getBoolean();
				} finally {
					variantProperty.dispose();
				}
			}
		}
		return false;
	}
	
	private void setDocumentVisible(OleAutomation document, boolean visible) {
		// Hide it: destination.Windows[0].Visible=0|1
		OleAutomation windows = getAutomationProperty(document, "Windows"); //$NON-NLS-1$
		try {
			OleAutomation window = getAutomationResult(windows, "Item", 1); //$NON-NLS-1$
			try {
				setProperty(window, "Visible", visible); //$NON-NLS-1$
			} finally {
				window.dispose();
			}
		} finally {
			windows.dispose();
		}
	}

	private OleAutomation openDocument(OleAutomation application, String doc) {
		// Open the first document: word.Documents.Open(p2)
		OleAutomation documents = getAutomationProperty(application, "Documents"); //$NON-NLS-1$
		try {
			OleAutomation document = getAutomationResult(documents, "Open", doc); //$NON-NLS-1$
			if (document == null) {
				throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_16, doc));
			}
			return document;
		} finally {
			documents.dispose();
		}
	}
	
	private OleAutomation getActiveDocument(OleAutomation application) {
		return getAutomationProperty(application, "ActiveDocument"); //$NON-NLS-1$
	}

	/*
	 * Create a handle to the application
	 */
	private OleAutomation createApplication() {
		return new OleAutomation(site);
	}

	/*
	 * When opening a new comparison, we want to close any existing site 
	 * and create a new one.
	 */
	private void resetSite(String filePath) {
		if (site != null && !site.isDisposed()) {
			disposeSite();
		}
		inplace = filePath != null;
		if (inplace) {
			site = new OleClientSite(frame, SWT.NONE, "Word.Document", new File(filePath)); //$NON-NLS-1$
		} else {
			site = new OleClientSite(frame, SWT.NONE, "Word.Application"); //$NON-NLS-1$
		}
	}

	private void disposeSite() {
		if (document != null) {
			closeDocument(document, null);
			document = null;
			OleAutomation application = createApplication();
			try {
				OleAutomation documents = getAutomationProperty(application, "Documents"); //$NON-NLS-1$
				try {
					Variant property = getVariantProperty(documents, "Count"); //$NON-NLS-1$
					if (property != null) {
						try {
							if (property.getLong() == 0) {
								// There are no other documents open so close the application
								Variant result = invoke(application, "Quit"); //$NON-NLS-1$
								if (result != null) {
									result.dispose();
								}
							}
						} finally {
							property.dispose();
						}
					}
				} finally {
					documents.dispose();
				}
			} finally {
				application.dispose();
			}
		}
		site.dispose();
		site = null;
	}

	public void saveAsDocument(String doc) {
		if (site == null || site.isDisposed()) return;
		if (inplace) {
			site.deactivateInPlaceClient();
			site.save(new File(doc), true);
			site.doVerb(OLE.OLEIVERB_SHOW);
		} else if (document != null) {
			try {
				Variant variant = invoke(document, "SaveAs", doc); //$NON-NLS-1$
				if (variant != null) {
					variant.dispose();
				}
			} catch (SWTException e) {
				// Ignore since this probably means the document was closed by the user
			}
		}
	}

	/**
	 * Return the OLEFrame for the comparison document.
	 * @return the OLEFrame for the comparison document
	 */
	public OleFrame getFrame() {
		return frame;
	}
	
	/**
	 * Dispose of the comparison.
	 */
	public void dispose() {
		try {
			disposeSite();
		} finally {
			if (!frame.isDisposed()) {
				frame.dispose();
			}
		}
	}

	/**
	 * Return whether the comparison document is dirty. This method handles 
	 * both an in-place document and a document opened in a separate window.
	 * @return weather the comparison document is dirty
	 */
	public boolean isDirty() {
		return (inplace && site != null && !site.isDisposed() && site.isDirty())
			|| (!inplace && getDocumentDirty(document));
	}
	
	/**
	 *	Initialize the workbench menus for proper menu merging
	 *  Copied from org.eclipse.ui.internal.editorsupport.win32OleEditor
	 */
	protected void initializeWorkbenchMenus(IWorkbenchWindow window) {
		//If there was an OLE Error or nothing has been created yet
		if (frame == null || frame.isDisposed())
			return;
		// Get the browser menu bar.  If one does not exist then
		// create it.
		Shell shell = frame.getShell();
		Menu menuBar = shell.getMenuBar();
		if (menuBar == null) {
			menuBar = new Menu(shell, SWT.BAR);
			shell.setMenuBar(menuBar);
		}

		// Swap the file and window menus.
		MenuItem[] windowMenu = new MenuItem[1];
		MenuItem[] fileMenu = new MenuItem[1];
		Vector containerItems = new Vector();

		for (int i = 0; i < menuBar.getItemCount(); i++) {
			MenuItem item = menuBar.getItem(i);
			String id = ""; //$NON-NLS-1$
			if (item.getData() instanceof IMenuManager)
				id = ((IMenuManager) item.getData()).getId();
			if (id.equals(IWorkbenchActionConstants.M_FILE))
				fileMenu[0] = item;
			else if (id.equals(IWorkbenchActionConstants.M_WINDOW))
				windowMenu[0] = item;
			else {
				if (window.isApplicationMenu(id)) {
					containerItems.addElement(item);
				}
			}
		}
		MenuItem[] containerMenu = new MenuItem[containerItems.size()];
		containerItems.copyInto(containerMenu);
		frame.setFileMenus(fileMenu);
		frame.setContainerMenus(containerMenu);
		frame.setWindowMenus(windowMenu);
	}

	/**
	 * Return whether the comparison document is being shown in-place or in
	 * a separate window.
	 * @return whether the comparison document is being shown in-place or in
	 * a separate window
	 */
	public boolean isInplace() {
		return inplace;
	}

	/**
	 * Return whether the comparison document is open.
	 * @return whether the comparison document is open
	 */
	public boolean isOpen() {
		return site != null && !site.isDisposed();
	}

	/**
	 * Close any open documents
	 */
	public void close() {
		if (isOpen()) {
			disposeSite();
		}	
	}
}
