package tests;

import org.junit.Test;

import algorithms.TypeInference;
import models.algebra.Expression;
import models.algebra.Variable;
import models.dataConstraintModel.ChannelMember;
import models.dataConstraintModel.ResourcePath;
import models.dataFlowModel.DataTransferChannel;
import models.dataFlowModel.DataTransferModel;
import parser.Parser;
import parser.Parser.TokenStream;
import parser.exceptions.ExpectedColon;
import parser.exceptions.ExpectedRightBracket;
import parser.exceptions.WrongJsonExpression;
import simulator.Simulator;
import simulator.SystemState;

public class SakodaTest {
	private DataTransferModel model;

	@Test
	public void test() {
		try {
			TokenStream stream = new Parser.TokenStream();
			Parser parser = new Parser(stream);
			
			model = new DataTransferModel();
			ResourcePath screen = new ResourcePath("screen");
			ResourcePath widgets = new ResourcePath(screen, "widgets");
			ResourcePath widget = new ResourcePath(widgets, new Variable("wid"));
			ResourcePath type = new ResourcePath(widget, "type");
			ResourcePath text = new ResourcePath(widget, "text");
			ResourcePath id = new ResourcePath(widget, "id");
			ResourcePath state = new ResourcePath(widget, "state");
			ResourcePath visible = new ResourcePath(widget, "visible");
			ResourcePath x = new ResourcePath(widget, "x");
			ResourcePath y = new ResourcePath(widget, "y");
			ResourcePath w = new ResourcePath(widget, "w");
			ResourcePath h = new ResourcePath(widget, "h");
			
			model.addResourcePath(screen);
			model.addResourcePath(widgets);
			model.addResourcePath(widget);
			model.addResourcePath(type);
			model.addResourcePath(id);
			model.addResourcePath(text);
			model.addResourcePath(state);
			model.addResourcePath(visible);
			model.addResourcePath(x);
			model.addResourcePath(y);
			model.addResourcePath(w);
			model.addResourcePath(h);
			
	//		JsonTerm elements = new JsonTerm();
	//		for(Element element : l.getElements()) {
	//			JsonTerm elem = new JsonTerm();
	//			elem.addMember("type", new Constant(element.getType()));
	//			elem.addMember("id", new Constant(element.getId()));
	//			elem.addMember("text", new Constant(element.getText()));
	//			elements.addMember(element.getId(), elem);
	//		}
	//		widgets.getResourceHierarchy().setInitialValue(elements);
			
			addNativeOutputChannel(stream, parser, screen, "ScreenUpdate", "curSc: Json", "update(curSc, nextSc)", "nextSc");
			addNativeOutputChannel(stream, parser, visible, "SetVisible", "curVisible: Bool", "setVisible(nextVisible)", "nextVisible");
			addNativeOutputChannel(stream, parser, text, "SetText", "curText: Str", "setText(nextText)", "nextText");
			addNativeInputChannel(stream, parser, state, "MouseEvent", "curState: Int", "mouseEvent(nextState)", "nextState");
			addNativeInputChannel(stream, parser, text, "MouseEvent", "curText: Str", "textEvent(nextText)", "nextText");
			
			TypeInference.infer(model);
			Simulator simulator = new Simulator(model);
			simulator.init();
			SystemState s = simulator.getCurState();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void addNativeOutputChannel(TokenStream stream, Parser parser, ResourcePath path,
			String channelName, String curStateName, String messageName, String nextStateName) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon {
		DataTransferChannel outputChannel = new DataTransferChannel(channelName);
		outputChannel.setNative(true);
		ChannelMember out = new ChannelMember(path);
		stream.addLine(curStateName);
		Expression curState = parser.parseTerm(stream, model);
		stream.addLine(messageName);
		Expression message = parser.parseTerm(stream, model);
		stream.addLine(nextStateName);
		Expression nextState = parser.parseTerm(stream, model);
		out.getStateTransition().setCurStateExpression(curState);
		out.getStateTransition().setMessageExpression(message);
		out.getStateTransition().setNextStateExpression(nextState);
		outputChannel.addChannelMemberAsInput(out);
		model.addChannel(outputChannel);
	}
	
	private void addNativeInputChannel(TokenStream stream, Parser parser, ResourcePath path,
			String channelName, String curStateName, String messageName, String nextStateName) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon {
		DataTransferChannel inputChannel = new DataTransferChannel(channelName);
		inputChannel.setNative(true);
		ChannelMember in = new ChannelMember(path);
		stream.addLine(curStateName);
		Expression curState = parser.parseTerm(stream, model);
		stream.addLine(messageName);
		Expression message = parser.parseTerm(stream, model);
		stream.addLine(nextStateName);
		Expression nextState = parser.parseTerm(stream, model);
		in.getStateTransition().setCurStateExpression(curState);
		in.getStateTransition().setMessageExpression(message);
		in.getStateTransition().setNextStateExpression(nextState);
		inputChannel.addChannelMemberAsOutput(in);
		model.addInputChannel(inputChannel);
	}
}