package ua.ansymo.hintco

import java.util.Map
import org.eclipse.core.runtime.Assert
import org.intocps.fmi.Fmi2Status
import org.intocps.fmi.FmuInvocationException
import org.intocps.fmi.IFmiComponent
import org.intocps.orchestration.coe.modeldefinition.ModelDescription
import org.intocps.orchestration.coe.modeldefinition.ModelDescription.ScalarVariable
import org.slf4j.Logger
import org.slf4j.LoggerFactory

abstract class FmuInstance implements IFmuInstance  {
	var IFmiComponent f
	var Map<String, ScalarVariable> varsByName = newHashMap()
	
	Logger logger = LoggerFactory.getLogger(typeof(FmuInstance))
	
	new (IFmiComponent f){
		if (f !== null){
			this.f = f
			loadVariables()			
		}
	}
	
	def loadVariables(){
		val modDesc = new ModelDescription(f.fmu.modelDescription)
		for (v : modDesc.scalarVariables){
			varsByName.put(v.name, v)
		}
	}
	
	override doStep(double currentCommunicationPoint, double communicationStepSize) throws FmuInvocationException {
		f.doStep(currentCommunicationPoint, communicationStepSize, true)
	}
	
	override enterInitializationMode() throws FmuInvocationException {
		f.enterInitializationMode()
	}
	
	override exitInitializationMode() throws FmuInvocationException {
		f.exitInitializationMode()
	}
	
	override setupExperiment() {
		f.setupExperiment(false, 0.0, 0.0, false, 0.0)
	}
	
	override getReal(String varName) {
		logger.debug(">getReal({})", varName)
		val res = f.getReal(#[varsByName.get(varName).valueReference])
		Assert.isTrue(res.status == Fmi2Status.OK)
		Assert.isTrue(!res.result.empty)
		val resD = res.result.head
		logger.debug("<getReal({}) = {}", varName, res)
		return resD
	}
	
	override setReal(String varName, double v) {
		logger.debug(">setReal({},{})", varName, v)
		val res = f.setReals(#[varsByName.get(varName).valueReference], #[v])
		Assert.isTrue(res == Fmi2Status.OK)
	}
	
	override free(){
		f.freeInstance()
	}
	
	override reset(){
		f.reset()
	}
	
}