@BEGIN FILE TEMPLATE@
@ENCHANTING HEADER@

import lejos.nxt.*;
import java.util.Properties;
import java.util.Random;
@IMPORTS@

@FUNCTIONS@

// This is the main entry point of the program
public class @BASEFILENAME@ {
    @USE "DECLARE THREAD TEMPLATE" FOR EACH FUNCTION@
    
    public static void main (String[] args) {
        @USE "CALL THREAD TEMPLATE" FOR EACH FUNCTION@    
    }
}

abstract class EnchantingScript extends Thread {
	@INITIALIZE PERIPHERALS@
	/*
    public static final Motor LEFT_MOTOR = Motor.C ;
    public static final Motor RIGHT_MOTOR = Motor.A;
    public static final Motor CLAW_MOTOR = Motor.B;
    public static final TouchSensor TOUCH_SENSOR = new TouchSensor(SensorPort.S1);
    public static final SoundSensor SOUND_SENSOR = new SoundSensor(SensorPort.S2);
    public static final LightSensor LIGHT_SENSOR = new LightSensor(SensorPort.S3);  
    public static final UltrasonicSensor ULTRASONIC_SENSOR = new UltrasonicSensor(SensorPort.S4); 
	*/

	public static final Random random = new Random();

    // VARIABLES
    // ---------
    
    private static Properties Variables = new Properties();
    public static String getVariable(String name) { return Variables.getProperty(name); }
    public static void setVariable(String name, String value) {
        Variables.setProperty(name, value);
    }
    public static void incrementVariable(String name, float inc) {
    	setVariable(name, StringFrom(NumberFrom(getVariable(name)) + inc));
    }
    public static void watchVariable(String name, boolean watch) {
    	// To do: monitor the given variable
    }
    
    // Initializing variables
    static {
        @USE "INITIALIZE VARIABLE TEMPLATE" FOR EACH VARIABLE@    
    }

    // HELPER FUNCTIONS
    // ----------------
    
    public static final void delay(float seconds) {
        Sound.pause((int)(1000.0f * seconds));  // time in milliseconds
    }
    
    public static final void playNote(double note, double beats) {
        int middleA = 440;  // hz
        double freq = (middleA / 32) * Math.pow(2.0, (note - 9) / 12);
        double ms = beats * 1000;   // assuming a tempo of 60 beats per minute 
        Sound.playNote(Sound.XYLOPHONE, (int)freq, (int)ms);
    }
    
    public static final int randomRange(int a, int b) {
    	// returns a random number between a and b inclusive
		int low = a;
		int diff = b - a;
		if (diff < 0) {
			low = b;
			diff = -diff;
		}
		return random.nextInt(diff + 1) + low;
    }
    	
    	
    
    // CONVERSION FUNCTIONS
    // --------------------
    
    public static final String StringFrom(Object o) {
        return o.toString();
    }
    
    // We will use float as our primary number type
    public static final float NumberFrom(String s) {
        try {
            return Float.parseFloat(s);
        } catch (NumberFormatException e) {
            return 0;
        }
    }
    public static final float NumberFrom(int i) {
        return (float)i;
    }
    public static final float NumberFrom(float f) {
        return f;
    }
    public static final float NumberFrom(double d) {
        return (float)d;
    }
    public static final float NumberFrom(boolean b) {
        if (b) {
            return 1.0f;
        }
        return 0.0f;
    }
    
    public static final int ToNearestInt(float f) {
    	return (int)(f + 0.5f);	// round to nearest integer
    }
    public static final int IntegerFrom(String s) {
    	return ToNearestInt(NumberFrom(s));
    }
    public static final int IntegerFrom(int i) {
    	return i;
    }
    public static final int IntegerFrom(float f) {
    	return ToNearestInt(NumberFrom(f));
    }
    public static final int IntegerFrom(double d) {
    	return ToNearestInt(NumberFrom(d));
    }    	
    public static final int IntegerFrom(boolean b) {
    	return b ? 1 : 0;
    }

    
    public static final boolean BooleanFrom(boolean b) {
        return b;
    }
    public static final boolean BooleanFrom(float f) {
        return f != 0.0f;
    }
    public static final boolean BooleanFrom(String s) {
        // A string equates to false if it is empty, "false", or "0"
        if (s == "") return false;
        if (s.equalsIgnoreCase("false")) return false;
        try {
            if (Float.parseFloat(s) == 0.0f) return false;
        } catch (NumberFormatException e) {}
        
        return true;
    }
    
    // In all of these comparison functions, we first assume that
    // we are comparing two numbers.  If we can't get two numbers to compare,
    // we compare strings.  [Comparing bools doesn't really make sense.]
    public static final boolean GreaterThan(String a, String b) {
        try {
            return Float.parseFloat(a) > Float.parseFloat(b);
        } catch (NumberFormatException e) { }
        return CompareStrings(a, b) == +1;
    }
    public static final boolean LessThan(String a, String b) {
        try {
            return Float.parseFloat(a) < Float.parseFloat(b);
        } catch (NumberFormatException e) { }
        return CompareStrings(a, b) == -1;
    }
    public static final boolean EqualTo(String a, String b) {
        try {
            return Float.parseFloat(a) == Float.parseFloat(b);
        } catch (NumberFormatException e) { }
        //return a.equalsIgnoreCase(b);        
        return CompareStrings(a, b) == 0;
    }
    public static final int CompareStrings(String a, String b) {
        // Compares two strings, ignoring case.
        // -1 means a < b, 0 means a == b, and +1 means a > b
        // Probably a slow function.
        String a2 = a.toLowerCase();
        String b2 = b.toLowerCase();
        int lenA = a2.length();
        int lenB = b2.length();
        for (int i = 0; i < lenA && i < lenB; ++i) {
            if (a2.charAt(i) != b2.charAt(i))
                return (a2.charAt(i) > b2.charAt(i)) ? +1 : -1;
        }
        if (lenA == lenB) return 0;
        return (lenA > lenB) ? +1 : -1; // longer string is greater
    }
}

@END TEMPLATE@

@BEGIN WHEN GREEN FLAG CLICKED TEMPLATE@
class @FUNCTIONNAME@ extends EnchantingScript {
    public @FUNCTIONNAME@() { }
    
    public void run() {
        @FUNCTIONBODY@
    }
}
@END TEMPLATE@

@DECLARE THREAD TEMPLATE@
private static @FUNCTIONNAME@ thread@FUNCTIONINDEX@; 
@END TEMPLATE@

@CALL THREAD TEMPLATE@
thread@FUNCTIONINDEX@ = new @FUNCTIONNAME@();
thread@FUNCTIONINDEX@.start();
@END TEMPLATE@

@INITIALIZE VARIABLE TEMPLATE@
setVariable("@VARIABLENAME@", "@VARIABLEVALUE@");
@END TEMPLATE@

