/**
 * Translate SFAL statements to ActionScript 3.0.
 * 
 * @author Antonio Cruz adc2104@columbia.edu
 * @version $Id: Translator.java,v 1.14 2007/12/16 07:30:46 admin Exp $
 */

import java.util.*;
import java.text.*;


public class Translator implements SfalWalkerTokenTypes {
	
	public Translator(SymbolTable st) { symTable = st; }
	SymbolTable symTable = null;
	
	static HashMap TRANSLATIONS = new HashMap();
	static {
		
		TRANSLATIONS.put("makesquare",
				"{0}.graphics.beginFill({3},100);\n" + 
				"{0}.graphics.drawRect(0,0,{2},{2});\n" +
				"{0}.graphics.endFill();\n" + 
				"{0}.x = 0;\n" +
				"{0}.y = 0;\n" +
				"addChild({0});\n");
		
		TRANSLATIONS.put("makerect",
				"{0}.graphics.beginFill({4},100);\n" + 
				"{0}.graphics.drawRect(0,0,{2},{3});\n" +
				"{0}.graphics.endFill();\n" + 
				"{0}.x = 0;\n" +
				"{0}.y = 0;\n" +
				"addChild({0});\n");
		
		TRANSLATIONS.put("makecircle",
				"{0}.graphics.beginFill({3},100);\n" + 
				"{0}.graphics.drawCircle(0,0,{2});\n" +
				"{0}.graphics.endFill();\n" + 
				"{0}.x = 0;\n" +
				"{0}.y = 0;\n" +
				"addChild({0});\n");
		
		TRANSLATIONS.put("makemovie",
				"package {\n" +
				"import flash.display.Sprite;\n" +
		        "import flash.text.TextField;\n" +
		        "import flash.events.Event;\n\n" +
		        "public class {2} extends Sprite {\n\n" +
		        "public function {2}() {\n");
		
		TRANSLATIONS.put("maketext",
				"{0}.text=\"{2}\";\n" +
				"addChild({0});");
		
		TRANSLATIONS.put("loop",
			"for (var {2}:int = {0}; {2} < {1}; {2}++)");

		TRANSLATIONS.put("setx", "{0}.x={3};\n");
		TRANSLATIONS.put("sety", "{0}.y={3};\n");
		TRANSLATIONS.put("getx", "x={2}.x;\n");
		TRANSLATIONS.put("gety", "y={2}.y;\n");
		
		TRANSLATIONS.put("settextx", "{0}.x={3};\n");
		TRANSLATIONS.put("settexty", "{0}.y={3};\n");
		TRANSLATIONS.put("gettextx", "x={2}.x;\n");
		TRANSLATIONS.put("gettexty", "y={2}.y;\n");
		TRANSLATIONS.put("addtotext", "{0}.appendText(\"{3}\");\n");

		TRANSLATIONS.put("makegroup", "addChild({0});");
		TRANSLATIONS.put("addtogroup", "{0}.addChild({3});\n");
		
		TRANSLATIONS.put("globalnumber", "");
		
		TRANSLATIONS.put("cos", "{0}=Math.cos({2});");
		TRANSLATIONS.put("sin", "{0}=Math.sin({2});");
	}
	
	/*
	 * 
	 */
	void checkForColor(String[] args) {
		String func=args[1], color, newcolor;
		if (func.equals("makesquare") || func.equals("makecircle")) {
			if (args.length < 4) return;
			color = args[3];
			newcolor = (String) Meta.WEB_COLORS.get(color.toLowerCase());
			if (newcolor == null) return;
			else args[3] = newcolor;
		}
		else if (func.equals("makerect")) {
			if (args.length < 5) return;
			color = args[4];
			newcolor = (String) Meta.WEB_COLORS.get(color.toLowerCase());
			if (newcolor == null) return;
			else args[4] = newcolor;
		}
		else return;
	}

	public String translate(int type, String s) {
		// System.err.println("TR: string: " + s);
		
		StringBuffer sb = new StringBuffer();
		
		switch(type) {
		case ASGN:
			String[] args = s.split(",");
			
			if (args.length < 1) return null;
			
			checkForColor(args);
			
			String translation = (String) TRANSLATIONS.get(args[1]);
			
			if (translation != null) {
				sb.append(MessageFormat.format(translation, args));
			}
			else {
				sb.append(args[0] + "=" + args[1] + ";");
			}
			break;
		case 1001: // loop
			translation = (String) TRANSLATIONS.get("loop");
			sb.append(MessageFormat.format(translation, s.split(",")));
			break;
			
		}
		
		return sb.toString();
	}
	
	StringBuffer aniBlock = new StringBuffer();
	
	/**
	 * 
	 * @return
	 */
	public String translateAnimator() {
		return aniBlock.toString();
	}
	
	
	/**
	 * 
	 * @param s
	 */
	public void buildAnimator(String s) {
		aniBlock.append(s).append('\n');
	}
	
	
    StringBuffer programBuffer = new StringBuffer();
	
	/**
	 * 
	 * @return
	 */
	public String getProgramBuffer() {
	    return programBuffer.toString();
    }
	
	
	/**
	 * 
	 * @param s
	 */
	public void buildProgramBuffer(String s) {
        programBuffer.append(s).append('\n');
	}
	
	
	/**
	 * Local variable declarations.
	 *
	 */
	public String translateSymbolTableLocal() {
		return writeVariableDeclarations("");
	}
	
	/**
	 * Global variable declarations.
	 *
	 */
	public String translateSymbolTable() {
		return writeVariableDeclarations("public ");
	}
	
	public String writeVariableDeclarations(String scope) {
		Set entries = symTable.table.entrySet();
		StringBuffer sb = new StringBuffer();
		for (Iterator itr = entries.iterator(); itr.hasNext(); ) {
			Map.Entry entry = (Map.Entry) itr.next();
			
			SymbolTable.SymTabEntry ste = (SymbolTable.SymTabEntry) entry.getValue();
			
			if (ste.declared == true) continue;
			
			if (ste.type != null ) {
				if (ste.type.equals("Sprite")) {
					sb.append(scope + "var " +
						entry.getKey() + ":Sprite = new " + ste.type + "();")
						.append('\n');
				}
				else if (ste.type.equals("TextField")) {
					sb.append(scope + "var " +
						entry.getKey() + ":TextField = new " + ste.type + "();")
						.append('\n');
				}
                else if (ste.type.equals("Number")) {
					sb.append(scope + "var " + entry.getKey() + ":Number = 0;")
					.append('\n');
				}
			}
			
			ste.declared = true;
		}
		return sb.toString();
	}
}
