/*
 *                                                                            
 *  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                                 
 *                                                                            
 *  Initial contribution:                                                      
 *     Loetz GmbH & Co. KG
 * 
 */
package org.eclipse.osbp.abstractstatemachine;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.channels.SelectableChannel;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.annotation.PreDestroy;

import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.osbp.dsl.common.datatypes.IDto;
import org.eclipse.osbp.runtime.common.filter.IQuery;
import org.eclipse.osbp.runtime.common.session.ISession;
import org.eclipse.osbp.ui.api.customfields.IBlobService;
import org.eclipse.osbp.ui.api.message.IMessageRequester;
import org.eclipse.osbp.ui.api.message.MessageEvent;
import org.eclipse.osbp.ui.api.message.MessageEvent.EventType;
import org.eclipse.osbp.ui.api.message.MessageRequesterEvent;
import org.eclipse.osbp.ui.api.metadata.IDSLMetadataService;
import org.eclipse.osbp.ui.api.report.IReportProvider;
import org.eclipse.osbp.ui.api.statemachine.IDataProvider;
import org.eclipse.osbp.ui.api.statemachine.IEventSource;
import org.eclipse.osbp.ui.api.statemachine.IPeripheral;
import org.eclipse.osbp.ui.api.statemachine.IStateMachine;
import org.eclipse.osbp.ui.api.themes.IThemeResourceService;
import org.eclipse.osbp.ui.api.user.IUser;
import org.eclipse.osbp.utils.vaadin.MessageDialog;
import org.eclipse.osbp.utils.vaadin.YesNoDialog;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.slf4j.Logger;

import com.vaadin.server.Page;
import com.vaadin.server.WebBrowser;
import com.vaadin.ui.UI;

public abstract class AbstractStateMachine implements IStateMachine, IMessageRequester.ClickRecipient {
	private static final String ENABLED = "Enabled";
	private static Logger logger = org.slf4j.LoggerFactory.getLogger("statemachine");
	protected Collection<IEventSource.Enabler> enablerList = new CopyOnWriteArraySet<>();
	protected Collection<IDataProvider.Provider> providerList = new CopyOnWriteArraySet<>();
	protected Collection<IPeripheral.Command> peripheralList = new CopyOnWriteArraySet<>();
	protected Map<String, MessageDialog> messageDialogs = new HashMap<>();
	protected Map<String, YesNoDialog> yesnoDialogs = new HashMap<>();
	protected WebBrowser webBrowser = Page.getCurrent().getWebBrowser();
	protected Timer timer;
	protected IUser user;
	protected Locale locale;
	protected IDSLMetadataService dslMetadataService;
	protected IThemeResourceService themeResourceService;
	protected IReportProvider reportProvider;
	protected IBlobService blobService;
	protected Map<String, Map<String, Object>> storage = new HashMap<>();
	protected SelectableChannel channel;
	protected String lastTrigger;
	protected IEclipseContext eclipseContext;

	private void addEventProvider(IEventSource.Enabler listener) {
		enablerList.add(listener);
	}

	private void removeEventProvider(IEventSource.Enabler listener) {
		enablerList.remove(listener);
	}

	@Override
	public void registerEnabler(IEventSource.Enabler listener) {
		addEventProvider(listener);
	}

	@Override
	public void unregisterEnabler(IEventSource.Enabler listener) {
		removeEventProvider(listener);
	}

	@Override
	public void setUser(IUser user) {
		this.user = user;
	}

	@Override
	public IUser getUser() {
		return user;
	}

	@Override
	public String getUserName() {
		return user.getUserName();
	}

	@Override
	public String getUserPassword() {
		return user.getExtraPassword();
	}

	@Override
	public String getUserEmail() {
		return user.getEmail();
	}

	@Override
	public String getUserPosition() {
		return user.getPosition();
	}

	@Override
	public String getUserPrintService() {
		return user.getPrintService();
	}

	@Override
	public void setLocale(Locale locale) {
		this.locale = locale;
	}

	@Override
	public Locale getLocale() {
		return locale;
	}

	@Override
	public void setDslMetadataService(IDSLMetadataService dslMetadataService) {
		this.dslMetadataService = dslMetadataService;
	}

	@Override
	public IDSLMetadataService getDslMetadataService() {
		return dslMetadataService;
	}

	@Override
	public IThemeResourceService getThemeResourceService() {
		return themeResourceService;
	}

	@Override
	public void setThemeResourceService(IThemeResourceService themeResourceService) {
		this.themeResourceService = themeResourceService;
	}

	@Override
	public void setReportProvider(IReportProvider reportprovider) {
		this.reportProvider = reportprovider;
	}

	@Override
	public IReportProvider getReportProvider() {
		return reportProvider;
	}

	@Override
	public IBlobService getBlobService() {
		return blobService;
	}

	@Override
	public void setBlobService(IBlobService blobService) {
		this.blobService = blobService;
	}

	@Override
	public void enable(String id, Boolean enable) {
		for (IEventSource.Enabler listener : enablerList) {
			listener.enable(listener, id, enable);
		}
	}

	@Override
	public void toggle(String id) {
		for (IEventSource.Enabler listener : enablerList) {
			listener.toggle(listener, id + ENABLED);
		}
		for (IDataProvider.Provider listener : providerList) {
			listener.toggle(listener, id + ENABLED);
		}
		for (IPeripheral.Command listener : peripheralList) {
			listener.toggle(listener, id + ENABLED);
		}
	}

	@Override
	public Object get(String id) {
		Object value;
		for (IEventSource.Enabler listener : enablerList) {
			value = listener.get(listener, id);
			if (value != null) {
				return value;
			}
		}
		for (IDataProvider.Provider listener : providerList) {
			value = listener.get(listener, id);
			if (value != null) {
				return value;
			}
		}
		for (IPeripheral.Command listener : peripheralList) {
			value = listener.get(listener, id);
			if (value != null) {
				return value;
			}
		}
		return null;
	}

	@Override
	public void set(String id, Object content) {
		for (IEventSource.Enabler listener : enablerList) {
			listener.set(listener, id, content);
		}
		for (IDataProvider.Provider listener : providerList) {
			listener.set(listener, id, content);
		}
		for (IPeripheral.Command listener : peripheralList) {
			listener.set(listener, id, content);
		}
	}

	@Override
	public void set(String id, String device, Object content) {
		for (IPeripheral.Command listener : peripheralList) {
			listener.set(listener, id, device, content);
		}
	}

	@Override
	public void clear(String id) {
		for (IEventSource.Enabler listener : enablerList) {
			listener.clear(listener, id);
		}
		for (IDataProvider.Provider listener : providerList) {
			listener.clear(listener, id);
		}
		for (IPeripheral.Command listener : peripheralList) {
			listener.clear(listener, id);
		}
	}

	@Override
	public void append(String id, String key) {
		for (IEventSource.Enabler listener : enablerList) {
			listener.append(listener, id, key);
		}
	}

	@Override
	public void remove(String id, int pos) {
		for (IEventSource.Enabler listener : enablerList) {
			listener.remove(listener, id, pos);
		}
	}

	@Override
	public void caption(String id, String value) {
		for (IEventSource.Enabler listener : enablerList) {
			listener.caption(listener, id, value);
		}
	}

	@Override
	public void image(String id, String imageName) {
		for (IEventSource.Enabler listener : enablerList) {
			listener.image(listener, id, imageName);
		}
	}

	@Override
	public void addDataProvider(IDataProvider.Provider listener) {
		providerList.add(listener);
	}

	@Override
	public void removeDataProvider(IDataProvider.Provider listener) {
		providerList.remove(listener);
	}

	@Override
	public void registerDataProvider(IDataProvider.Provider listener) {
		addDataProvider(listener);
	}

	@Override
	public void unregisterDataProvider(IDataProvider.Provider listener) {
		removeDataProvider(listener);
	}

	public void addPeripheral(IPeripheral.Command listener) {
		peripheralList.add(listener);
	}

	public void removePeripheral(IPeripheral.Command listener) {
		peripheralList.remove(listener);
	}

	@Override
	public void registerPeripheral(IPeripheral.Command listener) {
		addPeripheral(listener);
	}

	@Override
	public void unregisterPeripheral(IPeripheral.Command listener) {
		removePeripheral(listener);
	}

	@Override
	public Boolean find(String dtoName, IQuery query) {
		Boolean retVal;
		for (IDataProvider.Provider listener : providerList) {
			retVal = listener.find(listener, dtoName, query);
			if (retVal != null) {
				return retVal;
			}
		}
		return false;
	}

	@Override
	public Boolean find(String dtoName, String fieldName, Object search) {
		Boolean retVal;
		for (IDataProvider.Provider listener : providerList) {
			retVal = listener.find(listener, dtoName, fieldName, search);
			if (retVal != null) {
				return retVal;
			}
		}
		return false;
	}

	@Override
	public Collection<? extends IDto> findAll(String dtoName, IQuery query) {
		Collection<? extends IDto> retVal;
		for (IDataProvider.Provider listener : providerList) {
			retVal = listener.findAll(dtoName, query);
			if (retVal != null) {
				return retVal;
			}
		}
		return Collections.emptyList();
	}

	@Override
	public Collection<? extends IDto> findAll(String dtoName, String fieldName, Object search) {
		Collection<? extends IDto> retVal;
		for (IDataProvider.Provider listener : providerList) {
			retVal = listener.findAll(dtoName, fieldName, search);
			if (retVal != null) {
				return retVal;
			}
		}
		return Collections.emptyList();
	}

	@Override
	public void addTo(String dtoName, String listName, IDto dto) {
		for (IDataProvider.Provider listener : providerList) {
			listener.addTo(listener, dtoName, listName, dto);
		}
	}

	@Override
	public void removeFrom(String dtoName, String listName, IDto dto) {
		for (IDataProvider.Provider listener : providerList) {
			listener.removeFrom(listener, dtoName, listName, dto);
		}
	}

	@Override
	public void update(String dtoName) {
		for (IDataProvider.Provider listener : providerList) {
			listener.update(listener, dtoName, (IDto) listener.get(listener, dtoName));
		}
	}

	@Override
	public void reload(String dtoName) {
		for (IDataProvider.Provider listener : providerList) {
			listener.reload(listener, dtoName, (IDto) listener.get(listener, dtoName));
		}
	}

	@Override
	public void delete(String dtoName) {
		for (IDataProvider.Provider listener : providerList) {
			listener.delete(listener, dtoName, (IDto) listener.get(listener, dtoName));
		}
	}

	@Override
	public String getIPAddress() {
		// must define -Djava.net.preferIPv4Stack=true to always get IPv4 in
		// dual stack environments
		return webBrowser.getAddress(); // May be null, especially if running in
										// a Portlet.
	}

	@Override
	public String getHostName() {
		String hostName = null;
		try {
			InetAddress netAddress = InetAddress.getByName(webBrowser.getAddress());
			hostName = netAddress.getHostName();
		} catch (UnknownHostException e) {
			logger.error("{}", e);
		}
		return hostName;
	}

	@Override
	public boolean isItMe(String hostName) {
		String hostAddress;
		try {
			InetAddress netAddress = InetAddress.getByName(hostName);
			hostAddress = netAddress.getHostAddress();
		} catch (UnknownHostException e) {
			logger.error("{}", e);
			return false;
		}
		return getIPAddress().equals(hostAddress);
	}

	@Override
	public DateTime getNow() {
		return DateTime.now(DateTimeZone.UTC);
	}

	@Override
	public String getUserAgentInfo() {
		return webBrowser.getBrowserApplication();
	}

	@Override
	public Boolean isTouchDevice() {
		return webBrowser.isTouchDevice();
	}

	@Override
	public int getSceenWidth() {
		return webBrowser.getScreenWidth();
	}

	@Override
	public int getScreenHeight() {
		return webBrowser.getScreenHeight();
	}

	@PreDestroy
	void destroy() {
		timer.cancel();
		timer = null;
	}

	@Override
	public Locale getBrowserLocale() {
		return webBrowser.getLocale();
	}

	@Override
	public Boolean isHttps() {
		return webBrowser.isSecureConnection();
	}

	@Override
	public void schedule(IStateMachine statemachine, long milliseconds, MessageEvent event) {
		if (timer == null) {
			timer = new Timer();
		} else {
			timer.cancel();
			timer.purge();
			timer = new Timer();
		}
		timer.schedule(new EventSourceTask(statemachine, event), milliseconds);
	}

	class EventSourceTask extends TimerTask {
		private IStateMachine statemachine;
		private MessageEvent event;

		public EventSourceTask(IStateMachine statemachine, MessageEvent event) {
			this.statemachine = statemachine;
			this.event = event;
		}

		@Override
		public void run() {
			if (UI.getCurrent().isAttached())
				statemachine.processEvent(statemachine, event);
		}
	}

	/**
	 * @param doubleStr
	 * @return Double independent of locale
	 */
	@Override
	public Double parseDouble(String doubleStr) {
		String doubleStrIn = doubleStr.replaceAll("[^\\d,\\.]++", "");
		if (doubleStrIn.length() == 0) {
			return 0.0;
		}
		if (doubleStrIn.matches(".+\\.\\d+,\\d+$"))
			return Double.parseDouble(doubleStrIn.replaceAll("\\.", "").replaceAll(",", "."));
		if (doubleStrIn.matches(".+,\\d+\\.\\d+$"))
			return Double.parseDouble(doubleStrIn.replaceAll(",", ""));
		return Double.parseDouble(doubleStrIn.replaceAll(",", "."));
	}

	/**
	 * Format a double.
	 *
	 * @param value
	 *            the value
	 * @param length
	 *            the total length of the resulting string
	 * @param precision
	 *            the precision after decimal separator
	 * @return the string
	 */
	@Override
	public String formatDouble(Double value, int length, int precision) {
		String format = String.format("%% %d.%df", length, precision);
		return String.format(locale, format, value);
	}

	@Override
	public String getTranslation(String token) {
		if (dslMetadataService != null && locale != null) {
			return dslMetadataService.translate(locale.toLanguageTag(), token);
		}
		return token;
	}

	@Override
	public void closeMessage(String messageId) {
		if (messageDialogs.containsKey(messageId)) {
			MessageDialog messageDialog = messageDialogs.get(messageId);
			messageDialog.close();
			UI.getCurrent().removeWindow(messageDialog);
			messageDialogs.remove(messageId);
		}
	}

	@Override
	public void openMessage(String messageId) {
		openMessage(messageId, false);
	}

	@Override
	public void openMessage(String messageId, boolean okButton) {
		MessageDialog messageDialog = new MessageDialog(messageId, getTranslation(messageId));
		if (okButton) {
			messageDialog.addButton(getTranslation("ok"), new MessageEvent(EventType.MESSAGECLOSE, messageId));
			messageDialog.addButtonListener(this);
		}
		messageDialogs.put(messageId, messageDialog);
		UI.getCurrent().addWindow(messageDialog);
	}

	@Override
	public void openQuestion(String messageId, EventType type, String yesEvent, String noEvent, String cancelEvent) {
		MessageDialog messageDialog = new MessageDialog(messageId, getTranslation(messageId));
		messageDialog.addButton(getTranslation("yes"), new MessageEvent(type, yesEvent));
		messageDialog.addButton(getTranslation("no"), new MessageEvent(type, noEvent));
		messageDialog.addButton(getTranslation("cancel"), new MessageEvent(type, cancelEvent));
		messageDialog.addButtonListener(this);
		messageDialogs.put(messageId, messageDialog);
		UI.getCurrent().addWindow(messageDialog);
	}

	@Override
	public void messageButtonPressed(MessageRequesterEvent e) {
		MessageDialog messageDialog = messageDialogs.get(e.getId());
		messageDialog.close();
		UI.getCurrent().removeWindow(messageDialog);
		messageDialogs.remove(e.getId());
		this.processEvent(this, e.getEventData());
	}

	@Override
	public void dispatchMessages(MessageEvent event) {
		if (event.getType() == MessageEvent.EventType.TRIGGER) {
			lastTrigger = event.getId();
		}
		switch (event.getType()) {
		case ERROR:
			openMessage(event.getId(), true);
			break;
		case MESSAGEOPEN:
			openMessage(event.getId());
			break;
		case MESSAGECLOSE:
			closeMessage(event.getId());
			break;
		case STATUSOPEN:
		case STATUSCLOSE:
		default:
			break;
		}
	}

	@Override
	public Object getStorage(String key, String attribute) {
		if (storage.containsKey(key) && storage.get(key).containsKey(attribute)) {
			return storage.get(key).get(attribute);
		}
		return null;
	}

	@Override
	public Set<String> getStorageAttributes(String key) {
		if (storage.containsKey(key)) {
			return storage.get(key).keySet();
		}
		return Collections.emptySet();
	}

	@Override
	public void putStorage(String key, String attribute, Object content) {
		if (!storage.containsKey(key)) {
			storage.put(key, new HashMap<String, Object>());
		}
		storage.get(key).put(attribute, content);
	}

	@Override
	public void openChannel(SelectableChannel channel) {
		this.channel = channel;
	}

	@Override
	public SelectableChannel getChannel() {
		return channel;
	}

	@Override
	public void closeChannel() {
		if (channel != null) {
			try {
				channel.close();
			} catch (IOException e) { // NOSONAR
				// do nothing
			}
		}
	}

	@Override
	public String getLastTrigger() {
		return lastTrigger;
	}

	@Override
	public void setEclipseContext(IEclipseContext eclipseContext) {
		this.eclipseContext = eclipseContext;
	}

	@Override
	public IEclipseContext getEclipseContext() {
		return eclipseContext;
	}

	@Override
	public void sendSlaveData(Map<String, Object> data) {
		String currentInstanceId = (String) getEclipseContext().get("e4ApplicationInstanceId");
		List<ISession> sessions = POSServiceBinder.getSessionManager()
				.getSessions((s) -> s.get("e4ApplicationInstanceId").equals(currentInstanceId));
		if (!sessions.isEmpty()) {
			List<ISession> slaves = sessions.get(0).getSlaves();
			for (ISession slave : slaves) {
				slave.async(e -> {
					slave.sendData(data);
					return true;
				}, null);
			}
		}
	}
}
