/*******************************************************************************
 * <copyright>
 *
 * Copyright (c) 2005, 2016 SAP AG.
 * 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:
 *    SAP AG - initial API, implementation and documentation
 *    Bug 336488 - DiagramEditor API
 *    mgorning - Bug 347262 - DirectEditingFeature with TYPE_DIALOG type
 *    mgorning - Bug 377419 - Hide text in underlying GA while DirectEditing is enabled
 *    pjpaulin - Bug 352120 - Now uses IDiagramContainerUI interface
 *    mwenz - Bug 492362 - Error when calling Help (F1) while direct edit is active
 *
 * </copyright>
 *
 *******************************************************************************/
package org.eclipse.graphiti.ui.internal.parts.directedit;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.gef.editparts.ZoomListener;
import org.eclipse.gef.editparts.ZoomManager;
import org.eclipse.gef.requests.DirectEditRequest;
import org.eclipse.gef.tools.DirectEditManager;
import org.eclipse.graphiti.features.IDirectEditingFeature;
import org.eclipse.graphiti.features.context.IDirectEditingContext;
import org.eclipse.graphiti.func.IDirectEditing;
import org.eclipse.graphiti.func.IProposal;
import org.eclipse.graphiti.func.Proposal;
import org.eclipse.graphiti.ui.editor.DiagramBehavior;
import org.eclipse.graphiti.ui.internal.figures.GFMultilineText;
import org.eclipse.graphiti.ui.internal.figures.GFText;
import org.eclipse.graphiti.ui.internal.parts.ShapeEditPart;
import org.eclipse.graphiti.ui.internal.requests.GFDirectEditRequest;
import org.eclipse.graphiti.ui.internal.services.GraphitiUiInternal;
import org.eclipse.graphiti.ui.platform.ICellEditorProvider;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.IContentProposalProvider;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.CellEditorActionHandler;

/**
 * @noinstantiate This class is not intended to be instantiated by clients.
 * @noextend This class is not intended to be subclassed by clients.
 */
public class GFDirectEditManager extends DirectEditManager implements IDirectEditHolder {

	private IDirectEditingContext directEditingContext;

	private IDirectEditingFeature directEditingFeature;

	private DiagramBehavior diagramBehavior;

	private Font cellEditorFont = null;

	private IActionBars actionBars;

	private CellEditorActionHandler actionHandler;

	private IAction copy, cut, paste, undo, redo, find, selectAll, delete;

	private double cachedZoom = -1.0;

	private ZoomListener zoomListener = new ZoomListener() {
		public void zoomChanged(double newZoom) {
			updateScaledFont();
		}
	};

	public GFDirectEditManager(ShapeEditPart part, TextCellLocator cellEditorLocator) {
		super(part, null, cellEditorLocator);
		diagramBehavior = part.getConfigurationProvider().getDiagramBehavior();
	}

	public IDirectEditingContext getDirectEditingContext() {
		return directEditingContext;
	}

	public IDirectEditingFeature getDirectEditingFeature() {
		return directEditingFeature;
	}

	public void setDirectEditingContext(IDirectEditingContext directEditingContext) {
		this.directEditingContext = directEditingContext;
	}

	public void setDirectEditingFeature(IDirectEditingFeature directEditingFeature) {
		this.directEditingFeature = directEditingFeature;
	}

	public boolean isSimpleMode() {
		boolean ret = true;
		if (getDirectEditingFeature() != null) {
			if (getDirectEditingFeature().getProposalSupport() != null) {
				ret = false;
			}
		}
		return ret;
	}

	@Override
	protected CellEditor createCellEditorOn(Composite composite) {
		CellEditor ret = null;

		IFigure locatorFigure = getTextLocatorFigure();

		int editingType = directEditingFeature.getEditingType();

		if (editingType == IDirectEditing.TYPE_MULTILINETEXT) {
			int horizontalAlignment = SWT.LEFT;
			if (locatorFigure instanceof GFMultilineText) {
				int textAlignment = ((GFMultilineText) locatorFigure).getHorizontalAligment();
				if (textAlignment == PositionConstants.CENTER) {
					horizontalAlignment = SWT.CENTER;
				} else if (textAlignment == PositionConstants.RIGHT) {
					horizontalAlignment = SWT.RIGHT;
				}
			}
			ret = new TextCellEditor(composite, SWT.MULTI | SWT.WRAP | horizontalAlignment);
		} else if (editingType == IDirectEditing.TYPE_TEXT) {
			int horizontalAlignment = SWT.LEFT;
			if (locatorFigure instanceof GFText) {
				int textAlignment = ((GFText) locatorFigure).getLabelAlignment();
				if (textAlignment == PositionConstants.CENTER) {
					horizontalAlignment = SWT.CENTER;
				} else if (textAlignment == PositionConstants.RIGHT) {
					horizontalAlignment = SWT.RIGHT;
				}
			}
			ret = new TextCellEditor(composite, horizontalAlignment);
		} else if (directEditingFeature.getEditingType() == IDirectEditing.TYPE_DROPDOWN
				|| directEditingFeature.getEditingType() == IDirectEditing.TYPE_DROPDOWN_READ_ONLY) {
			String[] possibleValues = getPossibleValues();
			ret = new ComboBoxCellEditor(composite, possibleValues);
		} else if (editingType == IDirectEditing.TYPE_CUSTOM) {
			if (directEditingFeature instanceof ICellEditorProvider) {
				ret = ((ICellEditorProvider) directEditingFeature).createCellEditor(composite);
			} else {
				throw new UnsupportedOperationException("if custom type the feature must implement ICellEditorProvider"); //$NON-NLS-1$
			}
		}

		if (ret != null && editingType != IDirectEditing.TYPE_CUSTOM) {
			ret.setValidator(new GFCellEditorValidator(this, ret));
		}

		return ret;
	}

	private String[] getPossibleValues() {
		String[] possibleValues;
		if (isSimpleMode()) {
			possibleValues = directEditingFeature.getPossibleValues(directEditingContext);
		} else {
			IProposal[] proposals = directEditingFeature.getProposalSupport().getPossibleValues(directEditingContext);
			possibleValues = Proposal.proposalsToTexts(proposals);
		}
		return possibleValues;
	}

	private void disposeCellEditorFont() {
		if (cellEditorFont != null) {
			cellEditorFont.dispose();
			cellEditorFont = null;
		}
	}

	private void updateScaledFont() {
		if (getCellEditor().getControl() instanceof Text) {
			double zoom = 1.0;
			ZoomManager zoomMgr = (ZoomManager) getEditPart().getViewer().getProperty(ZoomManager.class.toString());
			if (zoomMgr != null) {
				zoom = zoomMgr.getZoom();
			}

			if (cachedZoom == zoom)
				return;
			cachedZoom = zoom;

			disposeCellEditorFont();
			Font lf = getTextLocatorFigure().getFont();
			FontData fd = lf.getFontData()[0];
			fd.setHeight((int) (fd.getHeight() * zoom));
			cellEditorFont = new Font(lf.getDevice(), fd);

			Text text = (Text) getCellEditor().getControl();
			text.setForeground(getTextLocatorFigure().getForegroundColor());
			text.setFont(cellEditorFont);
		}
	}

	@Override
	protected DirectEditRequest createDirectEditRequest() {
		GFDirectEditRequest req = new GFDirectEditRequest();
		req.setCellEditor(getCellEditor());
		req.setDirectEditingContext(this);
		return req;
	}

	@Override
	protected void initCellEditor() {
		String initialValue = directEditingFeature.getInitialValue(directEditingContext);

		if (directEditingFeature.getEditingType() == IDirectEditing.TYPE_MULTILINETEXT) {
			if (initialValue != null) {
				getCellEditor().setValue(initialValue);
			}
		} else if (directEditingFeature.getEditingType() == IDirectEditing.TYPE_DROPDOWN
				|| directEditingFeature.getEditingType() == IDirectEditing.TYPE_DROPDOWN_READ_ONLY) {
			ComboBoxCellEditor comboBoxCellEditor = (ComboBoxCellEditor) getCellEditor();

			setDirty(true);

			if (directEditingFeature.getEditingType() == IDirectEditing.TYPE_DROPDOWN_READ_ONLY) {
				CCombo cc = (CCombo) comboBoxCellEditor.getControl();
				cc.setEditable(false);
			}

			String[] possibleValues = getPossibleValues();
			comboBoxCellEditor.setValue(0);
			for (int x = 0; x < possibleValues.length; x++) {
				if (possibleValues[x].equals(initialValue))
					comboBoxCellEditor.setValue(x);
			}
		} else if (directEditingFeature.getEditingType() == IDirectEditing.TYPE_TEXT) {

			if (initialValue != null) {
				getCellEditor().setValue(initialValue);
			}

			if (directEditingFeature.isCompletionAvailable()) {

				String value = (String) getCellEditor().getValue();
				if (value == null)
					value = ""; //$NON-NLS-1$

				TextContentAdapter controlContentAdapter = new TextContentAdapter();
				IContentProposalProvider contentProposalProvider = new ContentProposalProvider(this);

				// if auto code completion disabled then open code completion on
				// CTRL+Space
				KeyStroke keyStroke = directEditingFeature.isAutoCompletionEnabled() ? null : KeyStroke.getInstance(
						SWT.CTRL, 32);

				ContentProposalAdapter contentProposalAdapter = new ContentProposalAdapter(
						getCellEditor().getControl(), controlContentAdapter, contentProposalProvider, keyStroke, null);
				contentProposalAdapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);
				contentProposalAdapter.addContentProposalListener(new ContentProposalListener(
						(TextCellEditor) getCellEditor()));
			}
		} else if (directEditingFeature.getEditingType() == IDirectEditing.TYPE_CUSTOM) {
			setDirty(true);
			getCellEditor().setValue(initialValue);
		}

		// this will force the font to be set
		cachedZoom = -1.0;
		updateScaledFont();
		ZoomManager zoomMgr = (ZoomManager) getEditPart().getViewer().getProperty(ZoomManager.class.toString());
		if (zoomMgr != null) {
			zoomMgr.addZoomListener(zoomListener);
		}

		getLocator().relocate(getCellEditor());

		// Hook the cell editor's copy/paste actions to the actionBars so that
		// they can
		// be invoked via keyboard shortcuts.
		IEditorPart activeEditor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
				.getActiveEditor();
		if (activeEditor != null) {
			actionBars = activeEditor.getEditorSite().getActionBars();
			saveCurrentActions(actionBars);
			actionHandler = new CellEditorActionHandler(actionBars);
			actionHandler.addCellEditor(getCellEditor());
			actionBars.updateActionBars();
		}
	}

	@Override
	protected void bringDown() {

		GFMultilineText mt = getMultilineText();
		if (mt != null) {
			mt.setSuppressText(false);
		}

		diagramBehavior.setDirectEditingActive(false);

		ZoomManager zoomMgr = (ZoomManager) getEditPart().getViewer().getProperty(ZoomManager.class.toString());
		if (zoomMgr != null) {
			zoomMgr.removeZoomListener(zoomListener);
		}

		if (actionHandler != null) {
			actionHandler.dispose();
			actionHandler = null;
		}
		if (actionBars != null) {
			restoreSavedActions(actionBars);
			actionBars.updateActionBars();
			actionBars = null;
		}

		if (diagramBehavior.isAlive()) {
			Display.getDefault().asyncExec(new Runnable() {
				@Override
				public void run() {
					GFDirectEditManager.super.bringDown();
					disposeCellEditorFont();
					GraphitiUiInternal.getWorkbenchService().getActiveStatusLineManager().setErrorMessage(null);
				}
			});
		}

		((ShapeEditPart) getEditPart()).delayDirectEditing();
	}

	@Override
	public void show() {

		GFMultilineText mt = getMultilineText();
		if (mt != null) {
			mt.setSuppressText(true);
		}

		diagramBehavior.setDirectEditingActive(true);
		// this is a bugfix
		// celleditor not shown initially when figure has insets
		// or mouse is not directly over control
		super.show();
		getLocator().relocate(getCellEditor());
	}

	private void restoreSavedActions(IActionBars actionBars) {
		actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), copy);
		actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), paste);
		actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), delete);
		actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), selectAll);
		actionBars.setGlobalActionHandler(ActionFactory.CUT.getId(), cut);
		actionBars.setGlobalActionHandler(ActionFactory.FIND.getId(), find);
		actionBars.setGlobalActionHandler(ActionFactory.UNDO.getId(), undo);
		actionBars.setGlobalActionHandler(ActionFactory.REDO.getId(), redo);
	}

	private void saveCurrentActions(IActionBars actionBars) {
		copy = actionBars.getGlobalActionHandler(ActionFactory.COPY.getId());
		paste = actionBars.getGlobalActionHandler(ActionFactory.PASTE.getId());
		delete = actionBars.getGlobalActionHandler(ActionFactory.DELETE.getId());
		selectAll = actionBars.getGlobalActionHandler(ActionFactory.SELECT_ALL.getId());
		cut = actionBars.getGlobalActionHandler(ActionFactory.CUT.getId());
		find = actionBars.getGlobalActionHandler(ActionFactory.FIND.getId());
		undo = actionBars.getGlobalActionHandler(ActionFactory.UNDO.getId());
		redo = actionBars.getGlobalActionHandler(ActionFactory.REDO.getId());
	}

	private GFMultilineText getMultilineText() {
		GFMultilineText mt = null;
		if (getTextLocatorFigure() instanceof GFMultilineText) {
			mt = (GFMultilineText) getTextLocatorFigure();
		}
		return mt;
	}

	private IFigure getTextLocatorFigure() {
		return ((TextCellLocator) getLocator()).getFigure();
	}
}
