package net.robertboehm.ld22;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.newdawn.slick.Color;
import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.state.transition.FadeInTransition;
import org.newdawn.slick.state.transition.FadeOutTransition;

public class GameScript extends Thread {

	public static final Pattern COMMAND_PATTERN = Pattern
			.compile("^([^ ]+)(.*)$");
	public static final int COMMAND_GROUP_INSTRUCTION = 1;
	public static final int COMMAND_GROUP_ARGUMENTS = 2;

	private static final Set<String> onceScripts = new HashSet<String>();
	private final String name;
	private final StateBasedGame game;
	private final IngameState state;

	public GameScript(StateBasedGame game, String name) {
		this(game, name, null);
	}

	public GameScript(StateBasedGame game, String name, IngameState state) {
		this.name = name;
		this.game = game;
		this.state = state;
	}

	@Override
	public void run() {
		try (BufferedReader r = new BufferedReader(GameAssets.getScript(name))) {
			runScript(r);
		} catch (NullPointerException e) {
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private IngameState getIngameState() {
		return state != null ? state : (IngameState) game.getCurrentState();
	}

	private void runScript(BufferedReader r) throws IOException {
		String line;
		Matcher m;
		while ((line = r.readLine()) != null) {
			try {
				String trimmedLine = line.trim();
				if (trimmedLine.isEmpty() || trimmedLine.startsWith("#"))
					continue;

				m = COMMAND_PATTERN.matcher(trimmedLine);
				if (m.matches()) {
					String cmd = m.group(COMMAND_GROUP_INSTRUCTION)
							.toLowerCase();
					String args = m.group(COMMAND_GROUP_ARGUMENTS).trim();
					String[] sArgs = args.split(" ");
					switch (cmd) {
					case "once":
						synchronized (onceScripts) {
							if (onceScripts.contains(name)) {
								return;
							}
							onceScripts.add(name);
						}
						break;
					case "wait":
						int delay = Integer.valueOf(args);
						try {
							Thread.sleep(delay);
						} catch (InterruptedException e) {
						}
						break;
					case "forbid_movement":
						AreYouStillThere.movementAllowed = false;
						break;
					case "allow_movement":
						AreYouStillThere.movementAllowed = true;
						break;
					case "enter_map2":
						if (sArgs.length == 3) {
							String mapName = sArgs[0];
							int spawnX = Integer.valueOf(sArgs[1])
									* AreYouStillThere.ZOOM;
							int spawnY = Integer.valueOf(sArgs[2])
									* AreYouStillThere.ZOOM;
							game.enterState(game.getCurrentStateID(),
									new FadeOutTransition(Color.white, 200),
									new FadeInTransition(Color.white, 200));
							getIngameState().enterMap(
									GameAssets.getMap(mapName), spawnX, spawnY);
						}
						break;
					case "enter_map":
						if (sArgs.length == 3) {
							String mapName = sArgs[0];
							int spawnX = Integer.valueOf(sArgs[1])
									* AreYouStillThere.ZOOM;
							int spawnY = Integer.valueOf(sArgs[2])
									* AreYouStillThere.ZOOM;
							System.out.println("ENTER MAP " + mapName);
							getIngameState().enterMap(
									GameAssets.getMap(mapName), spawnX, spawnY);
						}
						break;
					case "enter_mapgrid":
						game.enterState(MapgridState.findStateId(args));
						break;
					case "npc_init":
						if (sArgs.length == 4) {
							String npcId = sArgs[0];
							String npcCharset = sArgs[1];
							int spawnX = Integer.valueOf(sArgs[2])
									* AreYouStillThere.ZOOM;
							int spawnY = Integer.valueOf(sArgs[3])
									* AreYouStillThere.ZOOM;
							NPC npc = new NPC(
									GameAssets.getCharset(npcCharset),
									getIngameState());
							npc.setPosition(spawnX, spawnY);
							getIngameState().addNpc(npcId, npc);
						}
						break;
					case "npc_delete":
						getIngameState().deleteNpc(args);
						break;
					case "qmsg":
						AreYouStillThere.message.setText(args);
						try {
							Thread.sleep(1500 + args.length() * 50);
						} catch (InterruptedException e) {
						}
						AreYouStillThere.message.setText("");
						break;
					case "enter_outro":
						AreYouStillThere.showEnding = true;
						break;
					case "play_music":
						GameAssets.playMusic();
						break;
					case "quit":
						AreYouStillThere.getInstance().enterState(
								MainMenuState.STATE_ID,
								new FadeOutTransition(Color.black, 1000),
								new FadeInTransition(Color.black, 1000));
						break;
					case "msg":
						AreYouStillThere.message.setText(args);
						break;
					case "nomsg":
						AreYouStillThere.message.setText("");
						break;
					}
				}
			} catch (Exception e) {
			}
		}
	}

}
