/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package uce.parser;

import dict.IDictionary;
import dict.WNDictionary;
import dowser.Util;
import edu.smu.tspell.wordnet.SynsetType;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import usecase.Condition;
import usecase.Extension;
import usecase.OntValueCondition;
import usecase.OntoPhrase;
import usecase.Quantifier;
import usecase.Statement;
import usecase.StatementText.ObjectPhrase;
import usecase.UseCase;
import usecase.ValueRelation;

/**
 *
 * @author Chetan Pawgi
 */
public class SequenceDiagramGenerator {

	public String createSequenceDiagram(UseCase useCase) {
		StringBuffer bf = new StringBuffer();
		List<String> lifeLines = new ArrayList<String>();
		for (Statement stmt : useCase.getNormalCourse().getStatement()) {
			bf.append(processStatement(stmt, lifeLines));
		}
		StringBuffer ret = new StringBuffer();
		ret.append(".PS\n");
		ret.append("copy \"sequence.pic\";\n");
		lifeLines = Util.removeDuplicatesWithOrder(lifeLines);
		for (String actor : lifeLines) {
			ret.append(String.format("object(%s, \":%s\");\n", actor.toUpperCase(), actor));
		}
		ret.append("step();\n");
		ret.append(bf.toString());
		ret.append("step();\n");
		for (String actor : lifeLines) {
			ret.append(String.format("complete(%s);\n", actor.toUpperCase()));
		}
		ret.append(".PE");
		return ret.toString();
	}

	public String processStatement(Statement statement, List<String> lifeLines) {
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		PrintStream ps = new PrintStream(stream);
		internalProcessStatement(statement, ps, lifeLines);
		ps.close();
		return stream.toString();
	}
	private int m_FrameCount = 0;
	private int m_CommCount = 0;

	private void internalProcessStatement(Statement statement, PrintStream ps, List<String> lifeLines) {
		IDictionary dictionary = WNDictionary.getInstance();
		if (statement == null) {
			throw new IllegalArgumentException("statement can't be null IN internalProcessStatement");
		}
		String actor = statement.getText().getActor();
		String action = statement.getText().getAction();
		lifeLines.add(actor);
		action = WNDictionary.getInstance().getRootVerb(action);
		ObjectPhrase objPhrase = statement.getText().getObjectPhrase();
		Extension ext = statement.getText().getExtension();
		String extCond = "";
		if (ext != null) {
			if (ext.getUntil() != null) {
				extCond = "UNTIL ";
				for (Condition cond : ext.getUntil().getCondition()) {
					OntValueCondition ontVal = cond.getOntValueCondition();
					if (ontVal != null) {
						OntoPhrase Lphrase = ontVal.getLvalue();
						if (ontVal.getRelation() != ValueRelation.BY && ontVal.getRelation() != ValueRelation.TO) {
							String lVal = "";
							if (Lphrase.getAttribConcept() != null) {
								lVal = Lphrase.getAttribConcept().getAttribute() + " of " + Lphrase.getAttribConcept().getConcept();
							} else {
								lVal = Lphrase.getConcept();
							}
							extCond += lVal;
							extCond += " " + ontVal.getRelation().toString() + " ";
							extCond += ontVal.getRvalue();
						}
					}
				}
			} else if (ext.getFor() != null) {
				extCond = "FOR " + ext.getFor().getQuantity() + " " + ext.getFor().getUnitOftime();
			}
			if (!extCond.isEmpty()) {
				extCond = "[ " + extCond + " ]";
			}
		}
		//System.out.println(extCond);
		ps.println(String.format("active(%s);", actor.toUpperCase()));
		if (objPhrase == null) {
			ps.println(String.format("message(%s,%s,\"%s%s\");", actor.toUpperCase(), actor.toUpperCase(), action, extCond));
		} else {
			String objOfAction = DynamicModelValidator.getObjectOfAction(objPhrase);
			Quantifier quant = DynamicModelValidator.getObjectQuantifier(objPhrase);
			if (quant == Quantifier.SPECIFIC) {
				ps.println("step();");
				if (objPhrase.getOntValueCondition() != null) {
					int ind = objOfAction.indexOf("_OF_");
					if (objPhrase.getOntValueCondition().getRelation() == ValueRelation.TO && (dictionary.isSimilarTo(action, "change", SynsetType.VERB) || dictionary.isSimilarTo(action, "set", SynsetType.VERB))) {
						action = action + "_" + objOfAction.substring(0, ind);
						objOfAction = objOfAction.substring(ind + "_OF_".length());
					} else if (objPhrase.getOntValueCondition().getRelation() == ValueRelation.BY && (dictionary.isSimilarTo(action, "increase", SynsetType.VERB) || dictionary.isSimilarTo(action, "decrease", SynsetType.VERB))) {
						action = action + "_" + objOfAction.substring(0, ind) + "_BY";
						objOfAction = objOfAction.substring(ind + "_OF_".length());
					}
					action += "(" + objPhrase.getOntValueCondition().getRvalue() + ")";
				}
				ps.println(String.format("active(%s);", objOfAction.toUpperCase()));
				ps.println(String.format("message(%s,%s,\"%s\");", actor.toUpperCase(), objOfAction.toUpperCase(), action));
				ps.println(String.format("return_message(%s,%s,\"%s\");", objOfAction.toUpperCase(), actor.toUpperCase(), extCond));
				ps.println(String.format("inactive(%s);", objOfAction.toUpperCase()));
				ps.println("step();");
			} else {
				String frameName = "FRAME_" + m_FrameCount++;
				ps.println(String.format("begin_frame(%s,%s,\"%s\");", actor.toUpperCase(), frameName, "loop"));
				ps.println(String.format("message(%s,%s,\"%s%s\");", actor.toUpperCase(), objOfAction.toUpperCase(), action, extCond));
				ps.println("step();");
				ps.println(String.format("end_frame(%s,%s);", objOfAction.toUpperCase(), frameName));
			}
			lifeLines.add(objOfAction);
		}
		ps.println(String.format("inactive(%s);", actor.toUpperCase()));
	}
}
