/*******************************************************************************
 * Copyright (c) 2012 Rushan R. Gilmullin and others.
 * All rights reserved. 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:
 *     Rushan R. Gilmullin - initial API and implementation
 *******************************************************************************/

package org.eclipse.osbp.vaaclipse.presentation.renderers;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;

import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
import org.eclipse.e4.ui.model.application.ui.MElementContainer;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.MUILabel;
import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.model.application.ui.basic.MStackElement;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.services.internal.events.EventBroker;
import org.eclipse.e4.ui.workbench.IPresentationEngine;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.UIEvents.EventTags;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.osbp.runtime.designer.api.IDesignerService;
import org.eclipse.osbp.runtime.designer.api.IWidgetDesignConfigurator;
import org.eclipse.osbp.vaaclipse.api.VaadinExecutorService;
import org.eclipse.osbp.vaaclipse.presentation.dnd.VaadinDropHandler;
import org.eclipse.osbp.vaaclipse.publicapi.change.SimpleCommand;
import org.eclipse.osbp.vaaclipse.publicapi.resources.ResourceHelper;
import org.eclipse.osbp.vaaclipse.widgets.StackWidget;
import org.eclipse.osbp.vaaclipse.widgets.StackWidget.StateListener;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;

import com.vaadin.server.Resource;
import com.vaadin.ui.Component;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.TabSheet.CloseHandler;
import com.vaadin.ui.TabSheet.SelectedTabChangeEvent;
import com.vaadin.ui.TabSheet.SelectedTabChangeListener;
import com.vaadin.ui.TabSheet.Tab;

import fi.jasoft.dragdroplayouts.client.ui.LayoutDragMode;

@SuppressWarnings("restriction")
public class StackRenderer extends VaadinRenderer implements IDesignerService.IDesignListener {

	@Inject
	private EventBroker eventBroker;
	@Inject
	private EModelService modelService;
	@Inject
	private EditingDomain editingDomain;
	@Inject
	private EPartService partService;
	private Map<Component, MStackElement> vaatab2Element = new HashMap<Component, MStackElement>();
	private boolean ignoreTabSelChanges = false;

	@Inject
	VaadinExecutorService communicationManager;

	@Inject
	@Optional
	private IDesignerService designerService;

	private EventHandler tagListener = new EventHandler() {
		@Override
		public void handleEvent(Event event) {

			Object changedObj = event.getProperty(EventTags.ELEMENT);
			String eventType = (String) event.getProperty(UIEvents.EventTags.TYPE);
			String tag = (String) event.getProperty(UIEvents.EventTags.NEW_VALUE);

			int location = modelService.getElementLocation((MUIElement) changedObj);
			if (!(changedObj instanceof MPartStack) || location == EModelService.IN_SHARED_AREA) {
				return;
			}

			final MPartStack stack = (MPartStack) changedObj;
			StackWidget stackWidget = (StackWidget) stack.getWidget();

			if (UIEvents.EventTypes.ADD.equals(eventType)) {
				if (IPresentationEngine.MINIMIZED.equals(tag)) {
					stackWidget.setState(-1);
				} else if (IPresentationEngine.MAXIMIZED.equals(tag)) {
					stackWidget.setState(1);
				}
			} else if (UIEvents.EventTypes.REMOVE.equals(eventType)) {
				stackWidget.setState(0);
			}
		}
	};

	private EventHandler selectElementHandler = new EventHandler() {

		public void handleEvent(Event event) {
			Object element = event.getProperty(UIEvents.EventTags.ELEMENT);

			if (!(element instanceof MPartStack))
				return;

			MPartStack stack = (MPartStack) element;
			if (stack.getRenderer() != StackRenderer.this)
				return;

			if (stack.getSelectedElement() != null) {
				if (stack.getSelectedElement().getWidget() == null) {
					IPresentationEngine engine = (IPresentationEngine) context.get(IPresentationEngine.class.getName());
					engine.createGui(stack.getSelectedElement());

					int i = 0;
					for (MStackElement e : stack.getChildren()) {
						if (e == stack.getSelectedElement())
							break;

						if (e.getWidget() != null)
							i++;
					}

					addTab((TabSheet) stack.getWidget(), stack.getSelectedElement(), i);
				}

				if (stack.getSelectedElement() instanceof MPart) {
					MPart selected = (MPart) stack.getSelectedElement();
					if (selected.getObject() == null) {
						PartRenderer.renderPartContent(selected, selected.getContext());
					}
				}

				ignoreTabSelChanges = true;
				((TabSheet) stack.getWidget()).setSelectedTab((Component) stack.getSelectedElement().getWidget());
				ignoreTabSelChanges = false;
			}
		}
	};

	EventHandler itemUpdater = new EventHandler() {
		public void handleEvent(Event event) {
			MUIElement element = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);
			if (!(element instanceof MPart))
				return;

			MPart part = (MPart) element;

			String attName = (String) event.getProperty(UIEvents.EventTags.ATTNAME);
			Object newValue = event.getProperty(UIEvents.EventTags.NEW_VALUE);

			MPartStack stack = null;
			// is this a direct child of the stack?
			MPlaceholder placeholder = null;
			if (element.getParent() != null && element.getParent().getRenderer() == StackRenderer.this) {
				stack = (MPartStack) (MElementContainer<?>) element.getParent();
			} else {
				// Do we have any stacks with place holders for the element
				// that's changed?
				MWindow win = modelService.getTopLevelWindowFor(part);
				List<MPlaceholder> refs = modelService.findElements(win, null, MPlaceholder.class, null);
				if (refs != null) {
					for (MPlaceholder ref : refs) {
						if (ref.getRef() != part)
							continue;

						MElementContainer<?> refParent = ref.getParent();
						// can be null, see bug 328296
						if (refParent != null && refParent.getRenderer() instanceof StackRenderer) {
							placeholder = ref;
							stack = (MPartStack) refParent;
						}
					}
				}
			}

			if (stack != null) {
				Tab tab = ((StackWidget) stack.getWidget())
						.getTab((Component) (placeholder == null ? part.getWidget() : placeholder.getWidget()));
				if (tab != null)
					updateTab(tab, part, attName, newValue);
			}
		}
	};

	private void updateTab(Tab tab, MPart part, String attName, Object newValue) {
		if (UIEvents.UILabel.LABEL.equals(attName)) {
			String newName = (String) newValue;
			tab.setCaption(getLabel(part, newName));
		} else if (UIEvents.UILabel.ICONURI.equals(attName)) {
			Resource icon = part.getIconURI() != null ? ResourceHelper.createResource(part.getIconURI()) : null;
			tab.setIcon(icon);
		} else if (UIEvents.UILabel.TOOLTIP.equals(attName)) {
			String newTTip = (String) newValue;
			tab.setDescription(newTTip);
		} else if (UIEvents.UILabel.LOCALIZED_LABEL.equals(attName)) {
			String newName = (String) newValue;
			tab.setCaption(getLabel(part, newName));
		} else if (UIEvents.UILabel.LOCALIZED_TOOLTIP.equals(attName)) {
			String newTTip = (String) newValue;
			tab.setDescription(newTTip);
		} else if (UIEvents.Dirtyable.DIRTY.equals(attName)) {
			Boolean dirtyState = (Boolean) newValue;
			String text = tab.getCaption();
			boolean hasAsterisk = text.length() > 0 && text.charAt(0) == '*';
			if (dirtyState.booleanValue()) {
				if (!hasAsterisk) {
					tab.setCaption('*' + text);
				}
			} else if (hasAsterisk) {
				tab.setCaption(text.substring(1));
			}
		}
	}

	private String getLabel(MUILabel itemPart, String newName) {
		if (newName == null) {
			newName = ""; //$NON-NLS-1$
		}
		if (itemPart instanceof MDirtyable && ((MDirtyable) itemPart).isDirty()) {
			newName = '*' + newName;
		}
		return newName;
	}

	@PostConstruct
	public void postConstruct() {
		eventBroker.subscribe(UIEvents.ApplicationElement.TOPIC_TAGS, tagListener);
		eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT, selectElementHandler);
		eventBroker.subscribe(UIEvents.UILabel.TOPIC_ALL, itemUpdater);
		eventBroker.subscribe(UIEvents.Dirtyable.TOPIC_DIRTY, itemUpdater);
		eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_CHILDREN, childrenMoveUpdater);
	}

	@Override
	public void notify(IDesignerService.DesignEvent event) {
		updateDesigner(event.getType() == IDesignerService.EventType.ENABLED);
	}

	private void updateDesigner(boolean enabled) {
		IWidgetDesignConfigurator designConfigurator = context.get(IWidgetDesignConfigurator.class);
		if (designConfigurator != null) {
			for (Entry<Component, MStackElement> entry : vaatab2Element.entrySet()) {
				designConfigurator.configure(entry.getKey(), (EObject) entry.getValue(), enabled);
			}
		}
	}

	@PreDestroy
	public void preDestroy() {

		if (designerService != null) {
			designerService.removeListener(this);
		}

		eventBroker.unsubscribe(tagListener);
		eventBroker.unsubscribe(selectElementHandler);
		eventBroker.unsubscribe(itemUpdater);
		eventBroker.unsubscribe(childrenMoveUpdater);
	}

	// TODO for later use
	private EventHandler childrenMoveUpdater = new EventHandler() {
		public void handleEvent(Event event) {
			// Ensure that this event is for a MMenuItem
			if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MPartStack))
				return;

			@SuppressWarnings("unchecked")
			MElementContainer<MUIElement> stack = (MElementContainer<MUIElement>) event
					.getProperty(UIEvents.EventTags.ELEMENT);
			String type = (String) event.getProperty(UIEvents.EventTags.TYPE);

			if (UIEvents.EventTypes.MOVE.equals(type)) {
				StackWidget stackWidget = (StackWidget) stack.getWidget();
				stackWidget.removeAllComponents();

				processContents(stack);
			}
		}
	};

	@Override
	public void createWidget(MUIElement element, MElementContainer<MUIElement> parent) {
		if (!(element instanceof MPartStack))
			return;

		MPartStack stack = (MPartStack) element;
		StackWidget stackWidget = new StackWidget();
		stackWidget.setDragMode(LayoutDragMode.CLONE);

		stackWidget.setSizeFull();
		element.setWidget(stackWidget);

		IEclipseContext context = modelService.getContainingContext(stack).createChild();
		context.set(MPartStack.class, stack);

		VaadinDropHandler dropHandler = ContextInjectionFactory.make(VaadinDropHandler.class, context);
		stackWidget.setDropHandler(dropHandler);

		if (designerService != null) {
			designerService.addListener(this);

			if (designerService.isDesignMode()) {
				updateDesigner(true);
			}
		}
	}

	@Override
	public void processContents(final MElementContainer<MUIElement> container) {
		MPartStack stack = (MPartStack) (MElementContainer<?>) container;
		StackWidget stackWidget = (StackWidget) stack.getWidget();
		for (MStackElement element : stack.getChildren()) {
			if (element.isToBeRendered())
				addTab(stackWidget, (MStackElement) element, stackWidget.getComponentCount());
		}

		// if there are childs in stack and the selected element is not
		// specified for stack, set the first child as selected
		if (stack.getChildren().size() > 0 && stack.getSelectedElement() == null) {
			if (stack.getChildren().get(0).isVisible() && stack.getChildren().get(0).isToBeRendered()) {
				stack.setSelectedElement(stack.getChildren().get(0));
			}
		}

		if (stack.getSelectedElement() != null) {
			Component stackSelectedComponent = (Component) stack.getSelectedElement().getWidget();
			stackWidget.setSelectedTab(stackSelectedComponent);
		}
	}

	private void addTab(TabSheet parentPane, MStackElement element, int pos) {
		MUILabel mLabel;
		if (element instanceof MPlaceholder)
			mLabel = (MUILabel) ((MPlaceholder) element).getRef();
		else
			mLabel = (MUILabel) element;

		boolean closable = false;
		if (mLabel instanceof MPart)
			closable = ((MPart) mLabel).isCloseable();

		// Tab tab = parentPane.addTab((com.vaadin.ui.Component)
		// element.getWidget(), mLabel.getLocalizedLabel(), icon, pos);
		Tab tab = parentPane.addTab((com.vaadin.ui.Component) element.getWidget(), pos);
		tab.setCaption(mLabel.getLocalizedLabel());
		Resource icon = (mLabel.getIconURI() != null && !mLabel.getIconURI().trim().equals(""))
				? ResourceHelper.createResource(mLabel.getIconURI()) : null;
		if (icon != null) {
			tab.setIcon(icon);
		}
		tab.setClosable(closable);
		tab.setDescription(mLabel.getLocalizedTooltip());

		vaatab2Element.put((Component) element.getWidget(), element);

		if (designerService != null && designerService.isDesignMode()) {
			updateDesigner(designerService.isDesignMode());
		}
	}

	@SuppressWarnings("serial")
	@Override
	public void hookControllerLogic(final MUIElement element) {
		final StackWidget sw = (StackWidget) element.getWidget();

		int location = modelService.getElementLocation(element);
		if (location != EModelService.IN_SHARED_AREA) // if the stack not in
														// shared area
		{
			sw.addStateListener(new StateListener() {

				@Override
				public void stateChanged(int newState, int oldState) {
					if (oldState == 0 && newState == 1)
						setState(element, IPresentationEngine.MAXIMIZED);
					else if (oldState == 1 && newState == 0)
						setState(element, null);
					else if (oldState == 1 && newState == -1) {
						element.getTags().remove(IPresentationEngine.MINIMIZED);
						element.getTags().remove(IPresentationEngine.MAXIMIZED);
						element.getTags().add(IPresentationEngine.MINIMIZED);
					} else if (oldState == -1 && newState == 0) {
						element.getTags().remove(IPresentationEngine.MINIMIZED_BY_ZOOM);
						element.getTags().remove(IPresentationEngine.MINIMIZED);
					} else if (oldState == 0 && newState == -1)
						setState(element, IPresentationEngine.MINIMIZED);
				}

				private void setState(MUIElement element, String state) {
					element.getTags().remove(IPresentationEngine.MINIMIZED_BY_ZOOM);
					if (IPresentationEngine.MINIMIZED.equals(state)) {
						element.getTags().remove(IPresentationEngine.MAXIMIZED);
						element.getTags().add(IPresentationEngine.MINIMIZED);
					} else if (IPresentationEngine.MAXIMIZED.equals(state)) {
						element.getTags().remove(IPresentationEngine.MINIMIZED);
						element.getTags().add(IPresentationEngine.MAXIMIZED);
					} else {
						element.getTags().remove(IPresentationEngine.MINIMIZED);
						element.getTags().remove(IPresentationEngine.MAXIMIZED);
					}
				}
			});
		}

		sw.addSelectedTabChangeListener(new SelectedTabChangeListener() {
			public void selectedTabChange(SelectedTabChangeEvent event) {
				final MStackElement stackElement = vaatab2Element.get(sw.getSelectedTab());
				if (stackElement != null) {
					if (ignoreTabSelChanges)
						return;

					final MPartStack stack = (MPartStack) (MElementContainer<?>) stackElement.getParent();
					if (stack != null && stack.getSelectedElement() != stackElement) {

						SimpleCommand command = new SimpleCommand("Switch stack element") {
							final MStackElement oldStackElement = stack.getSelectedElement();

							@Override
							protected void doUndo() {
								stack.setSelectedElement(oldStackElement);
								activateStack(stack);
							}

							@Override
							protected void doExecute() {
								stack.setSelectedElement(stackElement);
								activateStack(stack);
							}
						};
						editingDomain.getCommandStack().execute(command);
					}
				}
			}
		});

		sw.setCloseHandler(new CloseHandler() {

			public void onTabClose(TabSheet tabsheet, Component tabContent) {
				MStackElement stackElement = vaatab2Element.get(tabContent);
				closePart(stackElement);
			}
		});
	}

	private void activateStack(MPartStack stack) {
		communicationManager.invokeLater(new ActivationRunnable(stack));
	}

	private class ActivationRunnable implements Runnable {

		private MPartStack stack;

		public ActivationRunnable(MPartStack stack) {
			this.stack = stack;
		}

		@Override
		public void run() {
			MStackElement stackElement = stack.getSelectedElement();
			// Ensure we're activating a stack in the current perspective,
			// when using a dialog to open a perspective
			// we end up in the situation where this stack is in the
			// previously active perspective
			int location = modelService.getElementLocation(stack);
			if ((location & EModelService.IN_ACTIVE_PERSPECTIVE) == 0
					&& (location & EModelService.OUTSIDE_PERSPECTIVE) == 0
					&& (location & EModelService.IN_SHARED_AREA) == 0)
				return;

			if (!isValid(stackElement))
				return;

			if (stackElement instanceof MPlaceholder)
				stackElement = (MStackElement) ((MPlaceholder) stackElement).getRef();

			IEclipseContext curContext = getContext(stackElement);
			if (curContext != null) {
				EPartService ps = (EPartService) curContext.get(EPartService.class.getName());
				if (ps != null)
					ps.activate((MPart) stackElement, true);
			}
		}
	}

	private boolean isValid(MUIElement element) {
		if (element == null || !element.isToBeRendered()) {
			return false;
		}

		if (element instanceof MApplication) {
			return true;
		}

		MUIElement parent = element.getParent();
		if (parent == null && element instanceof MWindow) {
			// might be a detached window
			parent = (MUIElement) ((EObject) element).eContainer();
		}

		if (parent == null) {
			// might be a shared part, try to find the placeholder
			MWindow window = modelService.getTopLevelWindowFor(element);
			return window == null ? false : isValid(modelService.findPlaceholderFor(window, element));
		}

		return isValid(parent);
	}

	private boolean isClosable(MPart part) {
		// if it's a shared part check its current ref
		if (part.getCurSharedRef() != null) {
			return !(part.getCurSharedRef().getTags().contains(IPresentationEngine.NO_CLOSE));
		}

		return part.isCloseable();
	}

	private boolean closePart(MStackElement stackElement) {

		MPart part = (MPart) ((stackElement instanceof MPart) ? stackElement : ((MPlaceholder) stackElement).getRef());
		if (!isClosable(part)) {
			return false;
		}

		IEclipseContext partContext = part.getContext();
		IEclipseContext parentContext = getContextForParent(part);
		// a part may not have a context if it hasn't been rendered
		IEclipseContext context = partContext == null ? parentContext : partContext;
		// Allow closes to be 'canceled'
		EPartService partService = (EPartService) context.get(EPartService.class.getName());
		if (partService.savePart(part, true)) {
			partService.hidePart(part);
			return true;
		}
		// the user has canceled out of the save operation, so don't close the
		// part
		return false;
	}

	@Override
	public void setVisible(MUIElement changedElement, boolean visible) {
		TabSheet tabPane = (TabSheet) changedElement.getWidget();
		tabPane.setVisible(visible);
	}

	@Override
	public void addChildGui(MUIElement child, MElementContainer<MUIElement> element) {
		if (!(child instanceof MStackElement))
			return;

		StackWidget sw = (StackWidget) element.getWidget();
		int index = indexOf(child, element);
		addTab(sw, (MStackElement) child, index);
	}
}
