package com.hammurapi.reasoning.impl;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;

import com.hammurapi.config.bootstrap.ConfigurationException;
import com.hammurapi.config.runtime.FactoryConfig;
import com.hammurapi.config.runtime.ResourceLoader;
import com.hammurapi.flow.runtime.FlowCompiler;
import com.hammurapi.reasoning.ForwardReasoningSession;
import com.hammurapi.reasoning.ForwardReasoningSessionFactory;
import com.hammurapi.reasoning.ReasoningException;
import com.hammurapi.reasoning.spi.model.RuleSet;

public class ForwardReasoningSessionFactoryImpl<F> implements ForwardReasoningSessionFactory<F> {
	
	private com.hammurapi.flow.Flow flowDef;
	private FactoryConfig factoryConfig;

	private static FactoryConfig cloneConfig(FactoryConfig master, URL contextURL) throws ReasoningException {
		try {
			FactoryConfig ret = (FactoryConfig) master.clone();
			if (ret.getContextUrl()==null) {
				ret.setContextUrl(contextURL);
			}
			return ret;
		} catch (CloneNotSupportedException e) {
			throw new ReasoningException(e);
		}
	}
	
	public ForwardReasoningSessionFactoryImpl(File ruleSetFile, FactoryConfig factoryConfig) throws ReasoningException, MalformedURLException {
		this(URI.createFileURI(ruleSetFile.getAbsolutePath()), cloneConfig(factoryConfig, ruleSetFile.toURI().toURL()));
	}
	
	public ForwardReasoningSessionFactoryImpl(String ruleSetUri, FactoryConfig factoryConfig) throws ReasoningException, MalformedURLException {
		this(URI.createURI(ruleSetUri), cloneConfig(factoryConfig, new URL(ruleSetUri)));
	}
	
	public ForwardReasoningSessionFactoryImpl(URI ruleSetUri, FactoryConfig factoryConfig) throws ReasoningException {
		this(ResourceLoader.load(ruleSetUri).getContents().get(0), factoryConfig);
	}
		
	public ForwardReasoningSessionFactoryImpl(EObject def, FactoryConfig factoryConfig) throws ReasoningException {        
		try {
			this.factoryConfig = (FactoryConfig) factoryConfig.clone();
		} catch (CloneNotSupportedException e) {
			throw new ReasoningException(e);
		}
		
		if (def instanceof RuleSet) {
			RuleSetToFlowCompiler ruleSetCompiler = new RuleSetToFlowCompiler();
			try {
				flowDef = ruleSetCompiler.compile((RuleSet) def, factoryConfig);
			} catch (ConfigurationException e) {
				throw new ReasoningException(e);
			}						
		} else if (def instanceof com.hammurapi.flow.Flow) {
			flowDef = (com.hammurapi.flow.Flow) def;
		}
		
		if (!FlowCompiler.isCompiled(flowDef)) {
			FlowCompiler flowCompiler = new FlowCompiler();
			try {
				flowDef = flowCompiler.compile(flowDef);
			} catch (ConfigurationException e) {
				throw new ReasoningException(e);
			}			
		}		
	}

	@Override
	public ForwardReasoningSession<F> createSession(Map<?, ?> properties) throws ReasoningException {
		try {			
			return new ForwardReasoningSessionImpl<F>(flowDef.create((FactoryConfig) factoryConfig.clone()), properties);
		} catch (Exception e) {
			throw new ReasoningException(e);
		}
	}		

}

