/*******************************************************************************
 * Copyright (c) 2009, 2019 Xored Software Inc and others.
 * 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
 * https://www.eclipse.org/legal/epl-v20.html
 *
 * Contributors:
 *     Xored Software Inc - initial API and implementation and/or initial documentation
 *******************************************************************************/
package org.eclipse.rcptt.tesla.internal.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.rcptt.tesla.core.Q7WaitUtils;
import org.eclipse.rcptt.tesla.core.context.ContextManagement.Context;
import org.eclipse.rcptt.tesla.core.info.AdvancedInformation;
import org.eclipse.rcptt.tesla.core.info.InfoFactory;
import org.eclipse.rcptt.tesla.core.info.Q7WaitInfoRoot;
import org.eclipse.rcptt.tesla.core.protocol.ElementCommand;
import org.eclipse.rcptt.tesla.core.protocol.GetStateResponse;
import org.eclipse.rcptt.tesla.core.protocol.IElementProcessorMapper;
import org.eclipse.rcptt.tesla.core.protocol.Nop;
import org.eclipse.rcptt.tesla.core.protocol.ProtocolFactory;
import org.eclipse.rcptt.tesla.core.protocol.ProtocolPackage;
import org.eclipse.rcptt.tesla.core.protocol.SelectCommand;
import org.eclipse.rcptt.tesla.core.protocol.SelectResponse;
import org.eclipse.rcptt.tesla.core.protocol.TeslaStream;
import org.eclipse.rcptt.tesla.core.protocol.raw.Command;
import org.eclipse.rcptt.tesla.core.protocol.raw.Element;
import org.eclipse.rcptt.tesla.core.protocol.raw.RawFactory;
import org.eclipse.rcptt.tesla.core.protocol.raw.Response;
import org.eclipse.rcptt.tesla.core.protocol.raw.ResponseStatus;
import org.eclipse.rcptt.tesla.internal.core.info.GeneralInformationCollector;
import org.eclipse.rcptt.tesla.internal.core.processing.ElementGenerator;
import org.eclipse.rcptt.tesla.internal.core.processing.ITeslaCommandProcessor;
import org.eclipse.rcptt.tesla.internal.core.processing.ITeslaCommandProcessor.PreExecuteStatus;
import org.eclipse.rcptt.util.Exceptions;

public abstract class AbstractTeslaClient implements IElementProcessorMapper {
	private boolean processing = false;
	private final ElementGenerator generator = new ElementGenerator();
	protected final List<Command> localQueue = new ArrayList<Command>();
	private Map<String, Set<ITeslaCommandProcessor>> elementProcessors = new HashMap<String, Set<ITeslaCommandProcessor>>();
	private final Map<Command, ITeslaCommandProcessor.PreExecuteStatus> preStatuses = new HashMap<Command, ITeslaCommandProcessor.PreExecuteStatus>();
	private final TeslaProcessorManager processors = new TeslaProcessorManager();
	private Context currentContext;
	private boolean closed = false;

	private final String id;
	private final AtomicInteger hasEvents = new AtomicInteger(-1);
	private AdvancedInformation lastFailureInformation;

	public AbstractTeslaClient(String id) {
		super();
		this.id = id;
		processors.initializeProcessors(this, id);
	}

	public String getID() {
		return id;
	}

	synchronized public void shutdown() {
		processors.terminate();
		elementProcessors.clear();
		closed = true;
	}

	protected abstract TeslaStream stream();

	@Override
	synchronized public void map(Element element, ITeslaCommandProcessor processor) {
		if (element != null && processor != null) {
			putProcessor(element, processor);
			processors.postSelect(element, new IElementProcessorMapper() {
				@Override
				public void map(Element element, ITeslaCommandProcessor processor) {
					putProcessor(element, processor);
				}
			});
		}
	}

	synchronized private void putProcessor(Element element, ITeslaCommandProcessor processor) {
		final String key = makeKey(element);
		Set<ITeslaCommandProcessor> set = this.elementProcessors.get(key);
		if (set == null) {
			set = new LinkedHashSet<ITeslaCommandProcessor>();
		}
		Set<ITeslaCommandProcessor> newSet = new LinkedHashSet<ITeslaCommandProcessor>();
		newSet.add(processor);
		newSet.addAll(set);
		// II: So that processors are iterated in
		// reverse order, i.e. processor which has
		// been put last, is iterated at first
		this.elementProcessors.put(key, newSet);
	}

	private SelectResponse handleSelect(SelectCommand cmd) {
		// Check for extensions first
		String kind = cmd.getData().getKind();
		SelectResponse response = processors.select(cmd, generator, this);
		if (response == null) {
			response = ProtocolFactory.eINSTANCE.createSelectResponse();
			response.setStatus(ResponseStatus.FAILED);
			response.setMessage("No Element with kind:" + kind + " is available for selection...");
		}
		if (response.getStatus().equals(ResponseStatus.FAILED)) {
			handleFailedResponse(cmd, response);
		}
		return response;
	}

	private String makeKey(Element uiElement) {
		return uiElement.getKind() + ":" + uiElement.getId();
	}

	synchronized public boolean processNext(Context context, Q7WaitInfoRoot info) {
		// Skip this event if we are already processing another one.
		if (!closed && !processing && (hasCommand() || !localQueue.isEmpty()) && canProceed(context, info)) {
			return doOneCommand(context, info);
		}
		return false;
	}

	public void hasEvent(String kind, String name, Q7WaitInfoRoot info) {
		hasEvents.incrementAndGet();
		Q7WaitUtils.startInfo(kind, name, info);
	}

	protected boolean canProceed(Context context, Q7WaitInfoRoot info) {
		hasEvents.set(0);
		boolean result = processors.canProceed(context, info);
		if (hasEvents.get() > 0) {
			return false;
		}
		return result;
	}

	public void clean() {
		lastFailureInformation = null;
		processors.clean();
		for (PreExecuteStatus status : preStatuses.values()) {
			status.clean();
		}
		preStatuses.clear();
		elementProcessors.clear();
	}

	private boolean preExecute(Command command, Q7WaitInfoRoot info) {
		if (command instanceof ElementCommand) {
			ElementCommand cmd = (ElementCommand) command;
			Element element = cmd.getElement();
			if (element != null) {
				Set<ITeslaCommandProcessor> processors = elementProcessors.get(makeKey(element));
				if (processors != null) {
					PreExecuteStatus preStatus = preStatuses.get(command);
					for (ITeslaCommandProcessor processor : processors) {
						if (processor != null) {
							try {
								PreExecuteStatus status = processor.preExecute(command, preStatus, info);
								if (status != null) {
									preStatuses.put(command, status);
									if (preStatus != status) {
										cleanPreStatus(preStatus);
									}
									if (!status.canExecute) {
										return false;
									}
								} else {
									preStatuses.remove(command);
									cleanPreStatus(preStatus);
								}
							} catch (Throwable e) {
								TeslaCore.log(e);
							}
						}
					}
				}
			}
		} else {
			PreExecuteStatus status = processors.preExecute(command, preStatuses.get(command), info);
			if (status != null && !status.canExecute) {
				preStatuses.put(command, status);
				return false;
			}
		}
		return true;
	}

	private void cleanPreStatus(PreExecuteStatus preStatus) {
		if (preStatus != null) {
			try {
				// We need to call clean to be sure status is finalized all
				// things.
				preStatus.clean();
			} catch (Throwable ee) {
				TeslaCore.log(ee);
			}
		}
	}

	synchronized public void addCommand(Command cmd) {
		localQueue.add(cmd);
		notifyUI();
	}

	public void notifyUI() {
		processors.notifyUI();
	}

	private boolean doOneCommand(Context context, Q7WaitInfoRoot info) {
		synchronized (this) {
			processing = true;
		}
		this.currentContext = context;
		Command command = null;
		try {
			final boolean isLocalQueue;
			if (!localQueue.isEmpty()) {
				command = localQueue.remove(0);
				isLocalQueue = true;
			} else {
				command = stream().readCommand();
				if (command == null) {
					return false;
				}
				isLocalQueue = false;
			}
			try {
				if (!preExecute(command, info)) {
					if (isLocalQueue) {
						localQueue.add(0, command);
					} else {
						localQueue.add(command);
					}
					return false;
				}
				stream().writeResponse(execute(command));
			} catch (Throwable e) {
				logException(e);
				stream().writeResponse(createErrorResponse(e));
			}
		} finally {
			synchronized (this) {
				processing = false;
			}
			currentContext = null;
		}
		return true;
	}

	private Response execute(final Command command) {
		// long startTime = System.currentTimeMillis();
		if (!(command instanceof Nop)) {
			lastFailureInformation = null;
		}
		if (command instanceof ElementCommand) {
			ElementCommand cmd = (ElementCommand) command;
			Element element = cmd.getElement();

			if (element != null) {
				Set<ITeslaCommandProcessor> processors = elementProcessors.get(makeKey(element));
				if (processors != null) {
					for (ITeslaCommandProcessor processor : processors) {
						if (processor != null) {
							Response response = processor.executeCommand(command, this);
							if (response != null) {
								if (response.getStatus().equals(ResponseStatus.FAILED)) {
									handleFailedResponse(command, response);
								}
								return response;
							}
						}
					}
				}
			}
		} else {
			Response response = processors.executeCommand(command, this, true);
			if (response != null) {
				if (response.getStatus().equals(ResponseStatus.FAILED)) {
					handleFailedResponse(command, response);
				}
				return response;
			}
		}
		if (command.eClass().getEPackage().equals(ProtocolFactory.eINSTANCE.getEPackage())) {
			switch (command.eClass().getClassifierID()) {
			case ProtocolPackage.SELECT_COMMAND:
				return handleSelect((SelectCommand) command);
			case ProtocolPackage.SHUTDOWN:
				shutdown();
				return RawFactory.eINSTANCE.createResponse();
			case ProtocolPackage.NOP:
				return RawFactory.eINSTANCE.createResponse();
			case ProtocolPackage.GET_STATE:
				GetStateResponse res = ProtocolFactory.eINSTANCE.createGetStateResponse();
				Element state = RawFactory.eINSTANCE.createElement();
				String returnedState = currentContext.getID();
				// System.out.println("RETURNED WAIT STATE:" +
				// returnedState);
				state.setId(returnedState);
				state.setKind("State");
				res.setState(state);
				return res;
			case ProtocolPackage.WAIT_FOR_STATE:
				return RawFactory.eINSTANCE.createResponse();
			case ProtocolPackage.ROLLBACK_TO_STATE:
				// TODO
				return RawFactory.eINSTANCE.createResponse();
			}
		}
		Response failed = RawFactory.eINSTANCE.createResponse();
		failed.setStatus(ResponseStatus.FAILED);
		failed.setMessage("Unsupported command");
		return failed;
	}

	private Response createErrorResponse(Throwable e) {
		Response errorResponse = RawFactory.eINSTANCE.createResponse();
		errorResponse.setStatus(ResponseStatus.FAILED);
		errorResponse.setMessage("Exception happened:\n" + Exceptions.toString(e)); // class
																					// name
																					// and
																					// exception
																					// message
		return errorResponse;
	}

	synchronized public AdvancedInformation getLastFailureInformation() {
		return lastFailureInformation;
	}

	synchronized public void clearLastFailureInformation() {
		lastFailureInformation = null;
	}

	private void handleFailedResponse(Command command, Response response) {
		if (response != null) {
			// Collect advanced information for this error
			AdvancedInformation information = getAdvancedInformation(command);
			this.lastFailureInformation = information;
			response.setAdvancedInformation(EcoreUtil.copy(information));
		}
	}

	synchronized public AdvancedInformation getAdvancedInformation(Command command) {
		// Collect advanced information
		AdvancedInformation information = InfoFactory.eINSTANCE.createAdvancedInformation();
		processors.collectInformation(information, command);
		GeneralInformationCollector.collectInformation(information);

		return information;
	}

	synchronized public void collectLastFailureInformation() {
		AdvancedInformation information = getAdvancedInformation(null);
		this.lastFailureInformation = information;
	}

	public abstract void logException(Throwable t);

	public abstract boolean hasCommand();

	public <T> T getProcessor(Class<T> clazz$) {
		return processors.getProcessor(clazz$);
	}

	public <T> List<T> getProcessors(Class<T> clazz$) {
		return processors.getProcessors(clazz$);
	}

}