package script;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.applet.AudioClip;
import java.awt.Toolkit;
import sun.audio.AudioStream;
import bGUI.BGame;
import bGUI.BGameCanvas;
import data.BDataModel;
import data.BPage;
import data.BPageModel;
import data.BShape;
import data.BShapeModel;
/**
*
* @author Chidozie Nwobilor
* class that defines what a script is
* need an instance of this class to access the methods.
*/
public class Script {
public static final String ON = "on";
public static final String CLICK = "click";
public static final String ENTER = "enter";
public static final String DROP = "drop";
public static final String GOTO = "goto";
public static final String PLAY = "play";
public static final String HIDE = "hide";
public static final String SHOW = "show";
public static final String BEEP = "beep";
private static Set<String> triggers;
private static Set<String> actions;
private static BDataModel data;
public Script(BDataModel data){
triggers = setUpTriggerSet();
actions = setUpActionsSet();
Script.data = data;
}
private static Set<String> setUpTriggerSet() {
Set<String> temp = new HashSet<String>();
temp.add(CLICK);
temp.add(ENTER);
temp.add(DROP);
return temp;
}
private static Set<String> setUpActionsSet() {
Set<String> temp = new HashSet<String>();
temp.add(GOTO);
temp.add(PLAY);
temp.add(HIDE);
temp.add(SHOW);
temp.add(BEEP);
return temp;
}
/**
* determines whether an incoming string is a valid script. Doesn't check to see
* if the names are valid though...
* @param s
* @return
*/
public static boolean isValid(String input){
Scanner sc = new Scanner(input);
if(!sc.next().toLowerCase().equals(ON)) return false;
String trigger = sc.next().toLowerCase();
if(!triggers.contains(trigger)) return false;
if(trigger.equals(DROP)){
String s = sc.next();
if(!data.hasShape(s) && !triggers.contains(s.toLowerCase())) return false;//have to see if requiring the other shape to be in the datamodel is problematic
}
return Validity(input.toLowerCase(), sc);
}
/*
* (non-javadoc)
* determines the validity of the rest of the string
*/
private static boolean Validity(String s, Scanner sc) {
while(sc.hasNext()){
String action = sc.next();
if(!actions.contains(action)) return false;
else{
if(!action.equals(BEEP)){
if(!sc.hasNext()) return false;
if(actions.contains(sc.next())) return false;
}
}
}
return true;
}
/**
* extracts the trigger in the given script. should only be used on scripts
* that have already been determined to be valid.
* @param script
*/
public static String extractTrigger(String script){
Scanner sc = new Scanner(script);
String s = "";
if(sc.hasNext()){
sc.next();
if(sc.hasNext())s += sc.next();
if(s.equals(DROP)){
return s + " " + sc.next();
}else{
return s;
}
}
return s;
}
/**
* extracts the shapeName in a dropScript
* @param script
* @return
*/
public static String extractShapeName(String script){
Scanner sc = new Scanner(script);
sc.next();
sc.next();
return sc.next();
}
public static void execute(String script, BGameCanvas canvas) {
//System.out.println(script);
ArrayList<String> actions = extractActions(script);
ExecuteActions(actions, canvas);
}
private static void ExecuteActions(ArrayList<String> actions, BGameCanvas canvas) {
int count = 0;
while(count < actions.size()){
String action = actions.get(count);
if(action.equals(BEEP)){
Toolkit.getDefaultToolkit().beep();
}else{
count++;
String target = "";
int i = count;
String temp = "";
while(i < actions.size()){
temp = actions.get(i);
if(Script.actions.contains(temp)){
count = i - 1;
break;
}
target += temp + " ";
i++;
}
if(i >= actions.size()) count = i;
//System.out.println(target);
target = target.substring(0, target.length() - 1);
if(action.equals(GOTO)){
//System.out.println(GOTO + " " + target + ";");
canvas.flipTo(new BPage(canvas.getData().getPage(target)));
}else if(action.equals(PLAY)){
//System.out.println(PLAY + " " + target);
canvas.getData().playAudio(target);
}else if(action.equals(HIDE)){
BShapeModel shape = canvas.getData().getShape(target);
if(shape != null) shape.setHidden(true);
}else{
BShapeModel shape = canvas.getData().getShape(target);
if(shape != null) shape.setHidden(false);
}
}
count++;
}
}
private static ArrayList<String> extractActions(String script) {
Scanner sc = new Scanner(script);
sc.next();
String trigger = sc.next();
if(IsDrop(trigger)) sc.next();
ArrayList<String> actions = new ArrayList<String>();
while(sc.hasNext()){
actions.add(sc.next());
}
return actions;
}
private static boolean IsDrop(String trigger) {
return trigger.equals(DROP);
}
public static Map<String, String> parseScript(String script){
System.out.println("---------------------------------------");
Map<String, String> scriptBlock = new HashMap<String, String>();
Scanner sc = new Scanner(script);
String s = "";
if(sc.hasNext()) s += sc.next() + " ";
while(sc.hasNext()){
String next = sc.next();
if(next.equals(ON)){
System.out.println(s);
if(isValid(s))scriptBlock.put(extractTrigger(s),s.toLowerCase());
s = "";
}
s += next + " ";
}
System.out.println(s);
if(s != "" && isValid(s))scriptBlock.put(extractTrigger(s), s);
return scriptBlock;
}
/**
* makes the inputted string script safe so that i don't have to deal with the problem of shape names with multiple
* words in them.
* @param name
* @return
*/
public static String makeScriptSafe(String name) {
Scanner s = new Scanner(name);
String result = "";
while(s.hasNext()){
result += s.next();
if(s.hasNext()) result += "_";
}
return result;
}
}