package com.hammurapi.reasoning.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Future;

import com.hammurapi.config.bootstrap.ConfigurationException;
import com.hammurapi.flow.runtime.Invocable;
import com.hammurapi.flow.runtime.Invoker;
import com.hammurapi.flow.runtime.ProcessingPathElement;
import com.hammurapi.flow.runtime.PropertySet;
import com.hammurapi.flow.runtime.impl.Inlineable;
import com.hammurapi.flow.runtime.impl.Joiner.InputConsumer;
import com.hammurapi.util.Context;

/**
 * Transition which doesn't do any processing - it simply passes invocation from source to targets.
 * @author Pavel Vlasov
 */
public class ReasoningPassThroughNode<F> extends ReasoningNodeBase<F> implements Inlineable {
	
	private List<Output<F>> outputs = new ArrayList<Output<F>>();

	private Invocable<KnowledgeBase<F>,InferenceToken<F>> invocable = new Invocable<KnowledgeBase<F>,InferenceToken<F>>() {

		@Override
		public Collection<Future<?>> invoke(
				KnowledgeBase<F> flowState,				 
				InferenceToken<F>[] args,				
				PropertySet properties,
				Context context,
				List<ProcessingPathElement> processingPath)
				throws Exception {
			Collection<Future<?>> ret = new ArrayList<Future<?>>();
			for (Output<F> o: outputs) {
				Collection<Future<?>> invokeResult = o.invocable.invoke(flowState, args, properties, context, processingPath);
				if (invokeResult!=null) {
					ret.addAll(invokeResult);
				}
			}
			return ret;
		}
		
	};
	
	@Override
	public Invocable<KnowledgeBase<F>,InferenceToken<F>> getInvocable(String pinName, Integer connectKey) {
		return invocable;
	}

	@Override
	public Invoker<KnowledgeBase<F>,InferenceToken<F>> getInvoker(String pinName, Integer connectKey) {
		Output<F> ret = new Output<F>(null, connectKey);
		outputs.add(ret);
		return ret;
	}
	
	@Override
	public void beforeConnect() throws ConfigurationException {
		// NOP		
	}
	
	@Override
	public void afterConnect() throws ConfigurationException {
		Collections.sort(outputs);
	}

	@Override
	public void addPin(String pinName, List<?> pin) {
		// NOP - pass-through node doesn't care about pin configuration.
		
	}

	@Override
	public boolean inline() {
		return true;
	}

	@Override
	protected Collection<Future<?>> process(
			KnowledgeBase<F> knowledgeBase,
			List<InferenceToken<F>>[] inputs, 
			PropertySet properties,
			Context context, List<ProcessingPathElement> processingPath,
			InputConsumer consumer,
			int activator) throws Exception {
		// Should never be invoked.
		throw new UnsupportedOperationException();
	}
}
