package TUGLaby;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Image;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedList;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JScrollPane;

import PrintGame.Action;
import PrintGame.Condition;
import PrintGame.IllegalDirectionException;
import PrintGame.Instruction;
import PrintGame.InstructionList;

import PrintGame.LabyrinthField;
import PrintGame.LevelHandler;
import PrintGame.PrintLabyrinth;
import PrintGame.Robot;
import PrintGame.TuringMachine;
import PrintGame.WriteLabToXML;

/*
 * JApplet.java
 *
 * Created on 16. August 2004, 22:30
 */

/**
 * 
 * @author user
 */
public class TUGLabyrinth extends javax.swing.JApplet implements Runnable {
    private static final long serialVersionUID = 7538087491086535801L;

    private static final int height = 700;

    private static final int width = 950;

    private RuleTreePanel rule_tree_panel_;

    private RulesBrickPanel rules_brick_panel_;

    private JScrollPane rule_tree_scrollpane_;

    private LabyrinthChoosePanel lab_choose_panel_;

    private HashMap brick_images_;

    private JButton start_button_;

    private String image_folder_;

    protected Thread th_;

    protected int level_type_;

    /**
     * ADDED FROM PrintGame
     * *********************************************************
     */
    protected final static boolean create_labyrinth_ = false; // Switch, nur

    // derzeit nötig

    //number of cells in a row and a col
    protected final static int ROWS = 20;

    protected final static int COLS = 20;

    //size of the labyrinth
    //    protected final static int LABYRINTH_HEIGHT = ROWS * CELL_HEIGHT;
    //    protected final static int LABYRINTH_WHITH = COLS * CELL_WHITH;

    Image way, wall, robot, diamond;

    protected static LabyrinthField labyrinth_field_;

    protected static LevelHandler level_handler_;

    protected static Robot robot_;

    protected static WriteLabToXML write_lab_;

    protected InstructionList instruct_list_;

    protected TuringMachine turing_machine_;

    protected PrintLabyrinth print_labyrinth_;

    protected boolean ready_to_run_;

    protected String file_name_;

    /**
     * ADDED FROM PrintGame
     * *********************************************************
     */

    /** Initializes the applet JApplet */
    public void init() {

        getContentPane().setLayout(null);
        this.setSize(width, height);

        String abs_filename = getParameter("abs_filename");

        abs_filename = "Games/Game.xml";
        ready_to_run_ = false;
        level_type_ = 1;
        // START TESTENVI
        start_button_ = new JButton();
        lab_choose_panel_ = new LabyrinthChoosePanel(1);
        getContentPane().add(start_button_);
        getContentPane().add(lab_choose_panel_);
        // END TESTENVI
        loadImages();

        rule_tree_panel_ = new RuleTreePanel(brick_images_);
        rules_brick_panel_ = new RulesBrickPanel(brick_images_);
        rule_tree_panel_.setPreferredSize(new Dimension(250, height - 10));

        rule_tree_scrollpane_ = new JScrollPane(rule_tree_panel_);

        print_labyrinth_ = new PrintLabyrinth(brick_images_, robot_, null);

        getContentPane().add(rule_tree_scrollpane_);
        getContentPane().add(rules_brick_panel_);
        getContentPane().add(print_labyrinth_);

        rule_tree_scrollpane_.setBounds(5, 5, 268, height - 10 + 1);
        rules_brick_panel_.setBounds(280, 5, 243, 62);
        print_labyrinth_.setBounds(280, 90, 400, 400);
        lab_choose_panel_.setBounds(700, 5, 200, 100);
        // START TESTENVI
        start_button_.setBounds(530, 5, 100, 30);
        start_button_.setBackground(Color.GREEN);
        start_button_.setForeground(Color.DARK_GRAY);
        start_button_.setText("Start !");
        start_button_.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                System.out.println("Rule Tree -->");
                instruct_list_ = new InstructionList();
                LinkedList listi = TUGLabyrinth.this.rule_tree_panel_
                        .getRuleList();
                for (int i = 0; i < listi.size(); i++) {
                    Instruction dummy = ((ConditionRulePanel) listi.get(i))
                            .getInstruction();
                    instruct_list_.addInstruction(dummy);
                }

                level_handler_ = new LevelHandler();
                level_handler_.setDocumentBase(getDocumentBase());
                level_handler_.loadGameXmlFile(file_name_);
                ready_to_run_ = true;

                th_ = new Thread(TUGLabyrinth.this);
                th_.start();
            }
        });

        // END TESTENVI
        URL new_url = null;
        try {
            new_url = new URL(getDocumentBase(), abs_filename);
        } catch (MalformedURLException ex) {
            System.err.println(ex.getMessage());
        }
        this.getContentPane().setBackground(Color.ORANGE);
        file_name_ = new_url.toString();

    }

    /**
     * This method is called from within the init() method to initialize the
     * form. WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void loadImages() {
        brick_images_ = new HashMap();
        // load the images which are display at the brick_rules panel
        image_folder_ = "Images";
        brick_images_.put("CONDITION_DEFAULT", loadImage("images.jpg"));
        brick_images_.put("CONDITION_HOVER", loadImage("images1.jpg"));
        brick_images_.put("ACTION_DEFAULT", loadImage("images2.jpg"));
        brick_images_.put("ACTION_HOVER", loadImage("images3.jpg"));
        brick_images_.put("ARROW_UP", loadImage("arrow_up.gif"));
        brick_images_.put("ARROW_DOWN", loadImage("arrow_down.gif"));
        brick_images_.put("ARROW_LEFT", loadImage("arrow_left.gif"));
        brick_images_.put("ARROW_RIGHT", loadImage("arrow_right.gif"));
        brick_images_.put("FREE_GROUND", loadImage("free_ground.gif"));
        brick_images_.put("WALL_GROUND", loadImage("wall_ground.gif"));

        brick_images_.put("EMPTY_FLOOR", loadImage("floor_empty.gif"));
        brick_images_.put("FLOOR_0", loadImage("floor_0.gif"));
        brick_images_.put("FLOOR_1", loadImage("floor_1.gif"));
        brick_images_.put("FLOOR_2", loadImage("floor_2.gif"));
        brick_images_.put("FLOOR_3", loadImage("floor_3.gif"));
        brick_images_.put("X_BUTTON", loadIcon("x_button.gif"));

        brick_images_.put("COND_NONE", loadImage("cond_none.gif"));
        brick_images_.put("COND_GREEN", loadImage("cond_green.gif"));
        brick_images_.put("COND_BLUE", loadImage("cond_blue.gif"));

        brick_images_.put("COND_NONE_1", loadImage("cond_none_1.gif"));
        brick_images_.put("COND_GREEN_1", loadImage("cond_green_1.gif"));
        brick_images_.put("COND_BLUE_1", loadImage("cond_blue_1.gif"));

        brick_images_.put("LAB_WAY", loadImage("way_3.jpg"));
        brick_images_.put("LAB_WALL", loadImage("way_2.jpg"));

        brick_images_
                .put("LAB_ROBOT_BLANK_UP", loadImage("robot_blank_up.gif"));
        brick_images_.put("LAB_ROBOT_BLANK_RIGHT",
                loadImage("robot_blank_right.gif"));
        brick_images_.put("LAB_ROBOT_BLANK_DOWN",
                loadImage("robot_blank_down.gif"));
        brick_images_.put("LAB_ROBOT_BLANK_LEFT",
                loadImage("robot_blank_left.gif"));

        brick_images_.put("LAB_ROBOT_BLUE_UP", loadImage("robot_blue_up.gif"));
        brick_images_.put("LAB_ROBOT_BLUE_RIGHT",
                loadImage("robot_blue_right.gif"));
        brick_images_.put("LAB_ROBOT_BLUE_DOWN",
                loadImage("robot_blue_down.gif"));
        brick_images_.put("LAB_ROBOT_BLUE_LEFT",
                loadImage("robot_blue_left.gif"));

        brick_images_
                .put("LAB_ROBOT_GREEN_UP", loadImage("robot_green_up.gif"));
        brick_images_.put("LAB_ROBOT_GREEN_RIGHT",
                loadImage("robot_green_right.gif"));
        brick_images_.put("LAB_ROBOT_GREEN_DOWN",
                loadImage("robot_green_down.gif"));
        brick_images_.put("LAB_ROBOT_GREEN_LEFT",
                loadImage("robot_green_left.gif"));

        brick_images_.put("LAB_CELLMARK0", loadImage("lab_cellmark0.gif"));
        brick_images_.put("LAB_CELLMARK1", loadImage("lab_cellmark1.gif"));
        brick_images_.put("LAB_CELLMARK2", loadImage("lab_cellmark2.gif"));
        brick_images_.put("LAB_CELLMARK3", loadImage("lab_cellmark3.gif"));

        brick_images_.put("LAB_DIAMOND", loadImage("diamond.gif"));

    }

    private Image loadImage(String name) {
        ImageIcon icon = null;
        if (image_folder_ == null)
            image_folder_ = "";
        try {
            icon = new ImageIcon(new URL(getCodeBase(), image_folder_ + "/"
                    + name));
            return icon.getImage();
        } catch (MalformedURLException e) {
            System.out.println("Failed to create URL:\n" + e);
            return null;
        }

    }

    private ImageIcon loadIcon(String name) {
        ImageIcon icon = null;
        if (image_folder_ == null)
            image_folder_ = "";
        try {
            icon = new ImageIcon(new URL(getCodeBase(), image_folder_ + "/"
                    + name));
            return icon;
        } catch (MalformedURLException e) {
            System.out.println("Failed to create URL:\n" + e);
            return null;
        }

    }

    //  -----------------------------------------------------------------------------

    public void createInstructList() {

        instruct_list_ = new InstructionList();
        //1 - Condition(N oder B, Markierung, Links Wand, Rechts Wand, Vorne
        // Wand)
        Instruction instruction = new Instruction(new Condition(0, 0, true,
                true, false), new Action(0, 0, Action.MOVE_AHEAD));
        instruct_list_.addInstruction(instruction);

        //2
        instruction = new Instruction(new Condition(0, 0, false, true, true),
                new Action(0, 0, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        //3
        instruction = new Instruction(new Condition(0, 0, true, false, true),
                new Action(0, 0, Action.MOVE_RIGHT));
        instruct_list_.addInstruction(instruction);

        //4
        instruction = new Instruction(new Condition(0, 0, false, false, true),
                new Action(0, 1, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        //5
        instruction = new Instruction(new Condition(0, 0, true, false, false),
                new Action(0, 1, Action.MOVE_AHEAD));
        instruct_list_.addInstruction(instruction);

        //6
        instruction = new Instruction(new Condition(0, 0, false, true, false),
                new Action(0, 1, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        //7
        instruction = new Instruction(new Condition(0, 0, true, true, true),
                new Action(1, 0, Action.MOVE_BACK));
        instruct_list_.addInstruction(instruction);

        // B in condition or/and action
        //8
        instruction = new Instruction(new Condition(1, 0, true, true, false),
                new Action(1, 0, Action.MOVE_AHEAD));
        instruct_list_.addInstruction(instruction);

        //9
        instruction = new Instruction(new Condition(1, 0, false, true, true),
                new Action(1, 0, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        //10
        instruction = new Instruction(new Condition(1, 0, true, false, true),
                new Action(1, 0, Action.MOVE_RIGHT));
        instruct_list_.addInstruction(instruction);

        //11
        instruction = new Instruction(new Condition(1, 1, false, false, true),
                new Action(0, 2, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        //12
        instruction = new Instruction(new Condition(1, 1, true, false, false),
                new Action(0, 2, Action.MOVE_AHEAD));
        instruct_list_.addInstruction(instruction);

        //13
        instruction = new Instruction(new Condition(1, 1, false, true, false),
                new Action(0, 2, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        //14
        instruction = new Instruction(new Condition(1, 2, false, false, true),
                new Action(1, 0, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        //15
        instruction = new Instruction(new Condition(1, 2, true, false, false),
                new Action(1, 0, Action.MOVE_AHEAD));
        instruct_list_.addInstruction(instruction);

        //16
        instruction = new Instruction(new Condition(1, 2, false, true, false),
                new Action(1, 0, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        //Vier Weg Kreuzung
        //1
        instruction = new Instruction(new Condition(0, 0, false, false, false),
                new Action(0, 1, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        //2
        instruction = new Instruction(new Condition(1, 1, false, false, false),
                new Action(0, 2, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        //3
        instruction = new Instruction(new Condition(1, 2, false, false, false),
                new Action(0, 3, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        //4
        instruction = new Instruction(new Condition(1, 3, false, false, false),
                new Action(1, 0, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        //Loops bei 3 Weg Kreuzungen
        instruction = new Instruction(new Condition(0, 1, false, false, true),
                new Action(1, 2, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        instruction = new Instruction(new Condition(0, 1, false, true, false),
                new Action(1, 2, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        instruction = new Instruction(new Condition(0, 1, true, false, false),
                new Action(1, 2, Action.MOVE_AHEAD));
        instruct_list_.addInstruction(instruction);

        //Loops bei 4 Weg Kreuzungen
        instruction = new Instruction(new Condition(0, 1, false, false, false),
                new Action(0, 2, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

        instruction = new Instruction(new Condition(0, 2, false, false, false),
                new Action(1, 3, Action.MOVE_LEFT));
        instruct_list_.addInstruction(instruction);

    }

    public void run() {
        try {
            int levels = level_handler_.getNumLevels();

            level_handler_.loadLevel(lab_choose_panel_.getCurrentSelected());
            labyrinth_field_ = level_handler_.getLabyrinthField();
            robot_ = new Robot();
            robot_.setPos(labyrinth_field_.getStartpointRow(), labyrinth_field_
                    .getStartpointCol());
            robot_.setStartDirection(labyrinth_field_.getStartDirection());
            // Testprogramm:
            turing_machine_ = new TuringMachine();
            turing_machine_.setLabyrinthField(labyrinth_field_);
            turing_machine_.setRobot(robot_);
            //createInstructList();
            turing_machine_.setInstructionList(instruct_list_);
            turing_machine_.setMode(TuringMachine.NORMAL);
            // Zeichnen des Labyrinths
            print_labyrinth_.setLabyrinthField(labyrinth_field_);
            print_labyrinth_.setRobot(robot_);

            //turing_machine_.setMode(TuringMachine.SINGLE_STEP);
            repaint();
            Thread.sleep(50);

            System.out.println("Turing Maschine started.");
            turing_machine_.start(print_labyrinth_);
            System.out.println("Anzahl der Schritte "
                    + turing_machine_.getNumSteps());
            System.out.println("Anzahl der gesammelten Diamanten "
                    + turing_machine_.getNumTakenDiamonds());

        } catch (IllegalDirectionException ex) {
            System.err.println(ex.getMessage());
        } catch (InterruptedException ex) {
            System.err.println(ex.getMessage());
        }
    }

}
