/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package BilaPani;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.io.File;
import java.util.Scanner;
import java.util.TimerTask;
import javax.swing.JPanel;

/**
 *
 * @author Vašek
 */
public class BPPanel extends JPanel {

    int size = 7; //7
    Tile[][] map;
    int width;
    int height;
    Point bp;
    Point tv;
    int wayLength = 0;
    int wayPos = 0;
    Point origin;
    Point current;
    boolean lastMoveForward = true;

    public BPPanel() {
    }

    public void setPath(File file) {
        read(file);
        /*Drawing drawing = new Drawing(this);
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(drawing, 0, 40);
        setLayout(new GridLayout(width, height));*/

    }

    public int findWay() { //6400
        int steps = 0;
        Point current = tv;
        int curNum = map[tv.x][tv.y].getWave();
        while ((current.x != bp.x || current.y != bp.y) && curNum > 0) {
            map[current.x][current.y].setColor(Color.green);
            Point winning = new Point();
            int best = curNum;
            if (tileIsOk(current.x - 1, current.y, curNum - 1)) {
                winning = new Point(current.x - 1, current.y);
                best = map[current.x - 1][current.y].getWave();

            } else if (tileIsOk(current.x + 1, current.y, curNum - 1)) {
                if (map[current.x + 1][current.y].getWave() < best) {
                    winning = new Point(current.x + 1, current.y);
                    best = map[current.x + 1][current.y].getWave();
                }

            } else if (tileIsOk(current.x, current.y - 1, curNum - 1)) {
                if (map[current.x][current.y - 1].getWave() < best) {
                    winning = new Point(current.x, current.y - 1);
                    best = map[current.x][current.y - 1].getWave();
                }

            } else if (tileIsOk(current.x, current.y + 1, curNum - 1)) {
                if (map[current.x][current.y + 1].getWave() < best) {
                    winning = new Point(current.x, current.y + 1);
                    best = map[current.x][current.y + 1].getWave();
                }
            }
            curNum = best;
            current = winning;
            steps++;
            //current = bp;
        }
        origin = bp;
        this.current = bp;
        return steps;
    }

    public boolean tileIsOk(int x, int y, int i) {
        if (x >= 0 && x < width && y >= 0 && y < height) {
            if (map[x][y].getWave() <= i) {
                return true;
            }
        }
        return false;
    }
    
    public void toggleWalls(){
    
    }
    
    public boolean singleWave() {
        boolean all;
        all = true;
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                if (map[x][y].getWave() == -2) {
                    all = false;
                } else if (map[x][y].getWave() != -1) {
                    if (waveAroundPoint(x, y)) {
                        all = false;
                    }
                } else {
                    all = false; ///
                }
            }
        }
        return all;
    }

    public int wave() {
        int rounds = 0;
        boolean all = false;
        while (!all && rounds < 6400) {
            all = singleWave();
            rounds++;
        }
        rounds = 0;
        while (singleWave() && rounds < 6400) {
            rounds++;
        }

        //singleWave();
        wayLength = map[tv.x][tv.y].getWave();
        return wayLength;
    }

    private boolean waveAroundPoint(int x, int y) {
        int i = map[x][y].getWave() + 1;
        boolean change = false;
        if (waveTile(x - 1, y, i)) {
            change = true;
        }
        if (waveTile(x, y + 1, i)) {
            change = true;
        }
        if (waveTile(x + 1, y, i)) {
            change = true;
        }
        if (waveTile(x, y - 1, i)) {
            change = true;
        }
        return change;
    }

    private boolean waveTile(int x, int y, int i) {
        if (x >= 0 && x < width && y >= 0 && y < height) {
            if (map[x][y].getWave() != -1) {
                //System.out.println("changing " + x + ", " + y + ":");
                return map[x][y].setWave(i);
            } else {
                return map[x][y].setWave(i);
            }
        } else {
            return false;
        }
    }

    public void read(File file) {
        try {
            Scanner scanner = new Scanner(file);
            String[] splitFirst = scanner.nextLine().split(" ");
            width = Integer.parseInt(splitFirst[0]);
            height = Integer.parseInt(splitFirst[1]);
            map = new Tile[width][height];
            String line = "";
            int y = 0;
            while (scanner.hasNextLine()) {
                line = scanner.nextLine();
                for (int x = 0; x < width; x++) {
                    switch (line.charAt(x)) {
                        case 'X':
                            map[x][y] = new Tile("X", TileType.WALL);
                            break;
                        case '&':
                            bp = new Point(x, y);
                            map[x][y] = new Tile("&", TileType.BP);
                            break;
                        case '#':
                            tv = new Point(x, y);
                            map[x][y] = new Tile("#", TileType.TV);
                            break;
                        case '@':
                            map[x][y] = new Tile("@", TileType.ZVED);
                            break;
                        default:
                            map[x][y] = new Tile(".", TileType.EMPTY);
                            break;
                    }
                }
                y++;
            }
            scanner.close();
        } catch (Exception e) {
        }
    }

    public void paintComponent(Graphics g) {
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                g.setColor(map[x][y].getColor());
                g.fillRect(x * size, y * size, size, size);
                /*g.setColor(Color.red);
                g.drawString(map[x][y].getWave() + "", x * size + 10, y * size + 10);*/
            }
        }
    }
    // <editor-fold defaultstate="collapsed" desc="asdf">

    public boolean forward() {
        boolean move = true;
        if (tileIsOkForGoing(current.x, current.y - 1, true)) {
            origin = current;
            current = new Point(current.x, current.y - 1);

        } else if (tileIsOkForGoing(current.x, current.y + 1, true)) {
            origin = current;
            current = new Point(current.x, current.y + 1);

        } else if (tileIsOkForGoing(current.x + 1, current.y, true)) {
            origin = current;
            current = new Point(current.x + 1, current.y);

        } else if (tileIsOkForGoing(current.x - 1, current.y, true)) {
            origin = current;
            current = new Point(current.x - 1, current.y);
        } else {
            move = false;
        }
        if (move) {
            map[origin.x][origin.y].setShowingBP(false);
            map[current.x][current.y].setShowingBP(true);
        }
        wayPos++;
        lastMoveForward = true;
        if (wayPos == wayLength) {
            return false;
        }
        return true;
    }

    public boolean back() {
        boolean move = true;
        if (tileIsOkForGoing(current.x, current.y - 1, false)) {
            origin = current;
            current = new Point(current.x, current.y - 1);

        } else if (tileIsOkForGoing(current.x, current.y + 1, false)) {
            origin = current;
            current = new Point(current.x, current.y + 1);

        } else if (tileIsOkForGoing(current.x + 1, current.y, false)) {
            origin = current;
            current = new Point(current.x + 1, current.y);

        } else if (tileIsOkForGoing(current.x - 1, current.y, false)) {
            origin = current;
            current = new Point(current.x - 1, current.y);
        } else {
            move = false;
        }
        if (move) {
            map[origin.x][origin.y].setShowingBP(false);
            map[current.x][current.y].setShowingBP(true);
        }
        wayPos--;
        lastMoveForward = false;
        if (wayPos == 0) {
            return false;
        }
        return true;
    }

    public boolean tileIsOkForGoing(int x, int y, boolean forward) {
        if (x >= 0 && x < width && y >= 0 && y < height) {
            if (map[x][y].getColor() == Color.green || map[x][y].getType() == TileType.BP) {
                if (!(x == origin.x && y == origin.y) && lastMoveForward == forward) {
                    return true;
                } else if (x == origin.x && y == origin.y && lastMoveForward != forward) {
                    return true;
                }
            }
        }
        return false;
    }
//</editor-fold>

    private class Drawing extends TimerTask {

        BPPanel panel;

        public Drawing(BPPanel panel) {
            this.panel = panel;
        }

        public void run() {
            panel.repaint();
        }
    }
}
