/**
 *                                                                            
 * Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
 *                                                                            
 * 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:   
 * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation 
 */
package org.eclipse.osbp.osgi.hybrid.api;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

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

import org.apache.commons.lang3.StringUtils;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.extensions.EventUtils;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.IPartListener;
import org.eclipse.osbp.bpm.api.IBlipBPMConstants;
import org.eclipse.osbp.dsl.common.datatypes.IDto;
import org.eclipse.osbp.eventbroker.EventBrokerMsg;
import org.eclipse.osbp.persistence.IPersistenceService;
import org.eclipse.osbp.runtime.web.vaadin.databinding.VaadinObservables;
import org.eclipse.osbp.ui.api.themes.IThemeResourceService;
import org.eclipse.osbp.ui.api.themes.IThemeResourceService.ThemeResourceType;
import org.eclipse.osbp.ui.api.useraccess.AbstractAuthorization.Permission;
import org.eclipse.osbp.ui.api.useraccess.AbstractAuthorization.PermissionResult;
import org.eclipse.osbp.ui.api.useraccess.AbstractPosition;
import org.eclipse.osbp.ui.api.useraccess.IPermissionList;
import org.eclipse.osbp.utils.common.IEntityIdModificationListenerView;
import org.eclipse.osbp.webserver.messagequeue.ECXMqMessageAttribute;
import org.eclipse.osbp.webserver.messagequeue.ECXMqMessageEvent;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vaadin.server.VaadinRequest;
import com.vaadin.ui.AbstractOrderedLayout;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;

public abstract class AbstractHybridVaaclipseView implements IHybridVaadinVaaclipseListener, IPartListener, IEntityIdModificationListenerView {
	
	@Inject
	IEventBroker eventBroker;

	@Inject
	protected IPersistenceService persistenceService;

	//
	// @Inject
	// private AbstractBlipBPMFunctionProvider taskProvider;
	//
	// @Inject
	// protected IBPMTaskClient taskClient;
	//
	// private String workloadDtoFqn;
	// private IDto initialWorkloadDto;
	// private Class<?> operativeDtoClass;
	// private List<IDto> initialOperativeDtos;

	private static final Logger LOGGER = LoggerFactory.getLogger(AbstractHybridVaaclipseView.class);

	public static enum RenderMode {
		SYNCHRONOUSLY, ASYNCHRONOUSLY
	}

	private final IEclipseContext fEclipseContext;
	private final MApplication fE4App;
	private final VerticalLayout fParent;
	private boolean fViewInitialized;
	protected final EventHandler fModifiedEntityIdsListener;
	private Map<String, Set<Object>> fListeningForEntityIdsModifications = new HashMap<>();

	private RenderMode renderMode = RenderMode.ASYNCHRONOUSLY;
	private boolean firstTime = true;
	private int pollingInterval = 2000;

	private RecursiveFocusBlurListener fRecursiveFocusBlurListener;

	/**
	 * <b><i><u>Warning:</u> never use initializing class attributes in the definition!<br>
	 * Due to Java specific internals the overriden method createView() will be called before that initializing will be done!<br>
	 * Instead put any initializing inside the overriden method createView()!</i></b>
	 * 
	 * @param parent
	 * @param context
	 * @param app
	 */
	public AbstractHybridVaaclipseView(final VerticalLayout parent, final IEclipseContext context, final MApplication app) {
		fE4App = app;
		fEclipseContext = context;
		fViewInitialized = false;
		fParent = parent;
		fModifiedEntityIdsListener = new EventHandler() {

			@Override
			public void handleEvent(Event event) {
				Object data = event.getProperty(EventUtils.DATA);
				// --- only if data contains an event broker message ---
				if (data instanceof EventBrokerMsg) {
					EventBrokerMsg eventBrokerMsg = (EventBrokerMsg) data;
					// eventBrokerMsg.getInt() == 1 means INSERT and no id check is required
					// otherwise it is an UPDATE and a id check is mandatory
					if (eventBrokerMsg.getInt() == 1) {
						refreshViewDueToModifiedEntityId(eventBrokerMsg.getName(), eventBrokerMsg.getId());
					} else {
						checkOnModifiedEntityId(eventBrokerMsg, true);
					}
				}
			}
		};
		fRecursiveFocusBlurListener = RecursiveFocusBlurListener.attachFor(fParent);
	}

	@PostConstruct
	public void initView() {
		preInit();
		VaadinObservables.getRealm(UI.getCurrent());
		UI.getCurrent().setPollInterval(pollingInterval);
		createView(fParent);
		postInit(null);
		renderData(true);
	}

	public void promptSecurityMessage(String message, AbstractOrderedLayout layout) {
		layout.removeAllComponents();
		FormLayout area = new FormLayout();
		layout.addComponent(area);

		Label msg = new Label(message);
		msg.setPrimaryStyleName("osbp");
		msg.setStyleName("osbpSecurityPrompt");
		if	(getThemeResourceService() != null) {
			msg.setIcon(getThemeResourceService().getThemeResource("locksview.gif", ThemeResourceType.IMAGE));
		}
		else {
			LOGGER.error("themeResourceService not set!");
		}
		area.addComponent(msg);
	}

	private String beautifyEntityName(String entityName) {
		return StringUtils.strip(entityName.replace('.', '/'), "/").toLowerCase();
	}

	private Object beautifyEntityId(Object id) {
		if (id instanceof String) {
			id = ((String) id).trim();
			try {
				Double.parseDouble((String) id);
				// --- if it's a double ---
				id = StringUtils.removeEnd((String) id, "0");
				id = StringUtils.removeEnd((String) id, ".");
			} catch (Exception e) {
				// NOTHING CAN BE DONE
			}
		}
		return id;
	}

	@Override
	public void resetListeningForEntityIdsModifications() {
		fListeningForEntityIdsModifications = null;
	}

	public boolean broadcastEntityIdModified(String packageName, String entityName, String id) {
		if (eventBroker != null) {
			return eventBroker.send(EventBrokerMsg.REFRESH_VIEW + EventBrokerMsg.getEntityIdModifiedCategory(packageName, entityName), new EventBrokerMsg(id, entityName));
		} else {
			return false;
		}
	}

	@Override
	public boolean checkOnModifiedEntityId(EventBrokerMsg message, boolean doRefresh) {
		return checkOnModifiedEntityId(message.getName(), message.getId(), doRefresh);
	}

	@Override
	public boolean checkOnModifiedEntityId(String entityName, Object id, boolean doRefresh) {
		// --- check if the entity sent is known ---
		entityName = beautifyEntityName(entityName);
		id = beautifyEntityId(id);
		Set<Object> ids = fListeningForEntityIdsModifications.get(entityName);
		if (ids instanceof Set) {
			// --- if the id for that entity is known ---
			if (ids.contains(id)) {
				// --- force refresh of the report ---
				if (doRefresh) {
					refreshViewDueToModifiedEntityId(entityName, id);
				}
				return true;
			}
		}
		return false;
	}

	@Override
	public void refreshViewDueToModifiedEntityId(String entity, Object id) {
		addEntityIdToModifyListener(entity, id);
	}

	@Override
	public void addEntityIdToModifyListener(String entityName, Object id) {
		// --- build the entity map if necessary ---
		if (fListeningForEntityIdsModifications == null) {
			fListeningForEntityIdsModifications = new HashMap<>();
		}
		entityName = beautifyEntityName(entityName);
		Set<Object> ids = fListeningForEntityIdsModifications.get(entityName);
		// --- build the ids set if necessary ---
		if (ids == null) {
			ids = new HashSet<>();
			fListeningForEntityIdsModifications.put(entityName, ids);
		}
		// --- put the primary key ---
		ids.add(beautifyEntityId(id));
	}

	@Override
	public void removeEntityIdFromModifyListener(String entityName, Object id) {
		// --- build the entity map if necessary ---
		if (fListeningForEntityIdsModifications != null) {
			Set<Object> ids = fListeningForEntityIdsModifications.get(beautifyEntityName(entityName));
			// --- build the ids set if necessary ---
			if (ids != null) {
				// --- put the primary key ---
				ids.remove(id);
			}
		}
	}

	public final MApplication getApplication() {
		return fE4App;
	}

	public final VerticalLayout getParent() {
		return fParent;
	}

	public final IEclipseContext getContext() {
		return fEclipseContext;
	}

	public final MPart getPart() {
		return (MPart) fEclipseContext.get(MPart.class);
	}

	public final String getProcessWorkloadDtoFqn() {
		return (String) getTransientDataVariable(IBlipBPMConstants.VARIABLE_PROCESS_WORKLOAD_DTO_FQN);
	}

	public final IDto getProcessInitialWorkloadDto() {
		return (IDto) getTransientDataVariable(IBlipBPMConstants.VARIABLE_PROCESS_WORKLOAD_DTO);
	}

	public final Class<?> getTaskOperativeDtoClass() {
		return (Class<?>) getTransientDataVariable(IBlipBPMConstants.VARIABLE_TASK_OPERATIVE_DTO_CLASS);
	}

	public final String getTaskOperativeDtoFqn() {
		return (String) getTransientDataVariable(IBlipBPMConstants.VARIABLE_TASK_OPERATIVE_DTO_FQN);
	}

	public final List<IDto> getTaskInitialOperativeDtos() {
		return (List<IDto>) getTransientDataVariable(IBlipBPMConstants.VARIABLE_TASK_OPERATIVE_DTOS);
	}

	public final Object getTransientDataVariable(String variable) {
		MPerspective perspective = getPerspective();
		if (perspective != null) {
			Map<String, Object> data = perspective.getTransientData();
			if (data != null) {
				return data.get(variable);
			}
		}
		return null;
	}

	public final MPerspective getPerspective() {
		MUIElement step = getPart();
		while ((step != null) && !(step instanceof MPerspective)) {
			step = step.getParent();
		}
		return (MPerspective) step;
	}

	public final IPersistenceService getPersistenceService() {
		return (IPersistenceService) fEclipseContext.get(IPersistenceService.class);
	}

	protected final boolean isViewInitialized() {
		return fViewInitialized;
	}

	/**
	 * <b><i><u>Warning:</u> put any initializing inside the your overriden method createView()!<br>
	 * Due to Java specific internals the overriden method createView() will be called before that initializing will be done!</i></b>
	 * 
	 * @param parent
	 */
	abstract protected void createView(final VerticalLayout parent);

	abstract protected void createComponents();

	// renderData is used for components that are not fully embedded in vaadin's connector structure
	// and must be repainted when parent window resizes
	// but can also be used to make component rendering asynchronously from view creation
	public void renderData() {
		LOGGER.debug("renderData not firsttime");
		renderData(false);
	}

	public void renderData(boolean firstTime) {
		// the first time we only want to be triggered by the initial createView process, not by changeLocale
		if (this.firstTime) {
			if (!firstTime) {
				LOGGER.debug("renderData ignored because not firsttime");
				return;
			} else {
				this.firstTime = false;
			}
		}
		if (UI.getCurrent() == null) {
			LOGGER.debug("renderData has no current ui");
			return;
		}
		if (renderMode == RenderMode.SYNCHRONOUSLY) {
			LOGGER.debug("render synchronously");
			UI.getCurrent().accessSynchronously(new Runnable() {
				@Override
				public void run() {
					createComponents();
				}
			});
		} else {
			LOGGER.debug("render asynchronously");
			UI.getCurrent().access(new Runnable() {
				@Override
				public void run() {
					createComponents();
				}
			});
		}
	}

	private IThemeResourceService getThemeResourceService() {
		if (fEclipseContext.containsKey(IThemeResourceService.class)) {
			return fEclipseContext.get(IThemeResourceService.class);
		}
		return null;
	}

	private EPartService getPartService() {
		if (fEclipseContext.containsKey(EPartService.class)) {
			return fEclipseContext.get(EPartService.class);
		}
		return null;
	}

	protected void preInit() {
		getPartService().addPartListener(this);
		HybridVaadinVaaclipseConnector.instance(fEclipseContext).addListener(this);
		HybridVaadinVaaclipseConnector.instance(fEclipseContext).setE4Application(fE4App);
	}

	@PreDestroy
	public void preDestroy() {
		fRecursiveFocusBlurListener.detach();
		HybridVaadinVaaclipseConnector.instance(fEclipseContext).removeListener(this);
		fListeningForEntityIdsModifications = null;
	}

	/**
	 * You <b>must call this at the end of the overridden init()</b>
	 */
	protected final void postInit(VaadinRequest request) {
		HybridVaadinVaaclipseConnector.instance(fEclipseContext).postInit(request);
		fViewInitialized = true;
		if (isAuthenticated()) {
			setAuthenticated(isAuthenticated());
		}
	}

	/**
	 * React in the application according to <code>authenticated</code>
	 * 
	 * @param authenticated
	 *            true if the user is authenticated now!
	 */
	public void setAuthenticated(boolean authenticated) {
		// now send the list of perspectives
		HybridVaadinVaaclipseConnector.instance(fEclipseContext).updatePerspectiveList();
	}

	protected final boolean isAuthenticated() {
		return HybridVaadinVaaclipseConnector.instance(fEclipseContext).isAuthenticated();
	}

	protected final IDto getAuthenticatedUser() {
		return HybridVaadinVaaclipseConnector.instance(fEclipseContext).getUser();
	}

	protected final AbstractPosition getAuthenticatedPosition() {
		return HybridVaadinVaaclipseConnector.instance(fEclipseContext).getPosition();
	}

	protected final Collection<String> getAuthenticatedRoles() {
		return HybridVaadinVaaclipseConnector.instance(fEclipseContext).getRoles();
	}

	protected final IPermissionList getAuthenticatedPermissions() {
		return HybridVaadinVaaclipseConnector.instance(fEclipseContext).getPermissions();
	}

	protected final PermissionResult isAuthenticatedPermitted(Permission permission) {
		return HybridVaadinVaaclipseConnector.instance(fEclipseContext).isPermitted(permission);
	}

	protected final Set<String> getAllUsers() {
		return HybridVaadinVaaclipseConnector.instance(fEclipseContext).getAllUsers();
	}

	/**
	 * Try to authenticate with the credentials given!<br>
	 * {@link #setAuthenticated(boolean)} will explicit be called!
	 * 
	 * @param portalId
	 * @param userName
	 * @param password
	 * @return true if the user was authenticated successful
	 */
	// protected boolean tryToAuthenticate(String portalId, String userName, String password) {
	// return HybridVaadinVaaclipseConnector.instance().tryToAuthenticate(portalId, userName, password);
	// }

	/**
	 * Logout from the Shiro API and send a LOGOUT event via ActiveMQ
	 */
	protected void logout() {
		HybridVaadinVaaclipseConnector.instance(fEclipseContext).logout();
	}

	/**
	 * handle any message received via ActiveMQ
	 * 
	 * @param event
	 * @param body
	 */
	@Override
	public final boolean onMessage(ECXMqMessageEvent event, Map<ECXMqMessageAttribute, Object> body) {
		boolean retcode = false;
		switch (event) {
		// !!! handled by connector ...
		case TRY_AUTHENTICATE:
		case DISPOSE:
		case LOGOUT:
			break;
		// ... handled by connector !!!
		case FOCUS_PERSPECTIVE:
			retcode = HybridVaadinVaaclipseConnector.instance(fEclipseContext).onFocusPerspective(body.get(ECXMqMessageAttribute.PERSPECTIVE_ID).toString());
			break;
		case REQUEST_ICON:
			retcode = HybridVaadinVaaclipseConnector.instance(fEclipseContext).requestIcon(body.get(ECXMqMessageAttribute.PERSPECTIVE_ID).toString());
			break;
		default:
			break;
		}
		return retcode;
	}

	@Override
	public void partActivated(MPart part) {
		HybridVaadinVaaclipseConnector.instance(fEclipseContext).activatePartStateRefresher(part);
		MPerspective active = HybridVaadinVaaclipseConnector.findCurrentPerspectiveFor(part == null ? getPartService().getActivePart() : part);
		if (active instanceof MPerspective) {
			HybridVaadinVaaclipseConnector.instance(fEclipseContext).updatePerspectiveList();
			HybridVaadinVaaclipseConnector.instance(fEclipseContext).updateFocusPerspective(active.getElementId());
		} else if ((part != null || getPartService().getActivePart() != null)) {
			LOGGER.debug("part activated:" + (part == null ? "<null>" : part.getElementId() + " '" + part.getLabel() + "'"));
			List<MPerspective> existing = HybridVaadinVaaclipseConnector.instance(fEclipseContext).findPerspectives();
			for (MPerspective perspective : existing) {
				LOGGER.debug("    perspective:" + perspective.getElementId() + " '" + perspective.getLabel() + "'");
			}
			LOGGER.debug("  COULD NOT find the corresponding perspective :-(");
		}
	}

	@Override
	public void partBroughtToTop(MPart part) {
		HybridVaadinVaaclipseConnector.instance(fEclipseContext).activatePartStateRefresher(part);
	}

	@Override
	public void partDeactivated(MPart part) {
	} // NOP

	@Override
	public void partHidden(MPart part) {
	} // NOP

	@Override
	public void partVisible(MPart part) {
	} // NOP

	/**
	 * Try to authenticate with the credentials given!<br>
	 * {@link #setAuthenticated(boolean)} will explicit be called!
	 * 
	 * @param portalId
	 * @param userName
	 * @param password
	 * @return true if the user was authenticated successful
	 */
	protected boolean tryToAuthenticate(String portalId, String userName, String password) {
		return HybridVaadinVaaclipseConnector.instance(fEclipseContext).tryToAuthenticate(portalId, userName, password);
	}

	public RenderMode getRenderMode() {
		return renderMode;
	}

	public void setRenderMode(RenderMode renderMode) {
		this.renderMode = renderMode;
	}

	public int getPollingInterval() {
		return pollingInterval;
	}

	public void setPollingInterval(int pollingInterval) {
		this.pollingInterval = pollingInterval;
	}

}
