package view;

import com.codingame.gameengine.module.entities.GraphicEntityModule;
import com.codingame.gameengine.module.entities.Group;
import com.codingame.gameengine.module.entities.Polygon;
import com.codingame.gameengine.module.entities.Sprite;
import com.codingame.gameengine.module.entities.Text;
import com.codingame.gameengine.module.toggle.ToggleModule;
import com.codingame.gameengine.module.tooltip.TooltipModule;


import com.codingame.game.Player;

import engine.*;

public class BoardView {
    private static final int WIDTH = 1920;
    private static final int HEIGHT = 1080;
    private GraphicEntityModule graphics;
    private Board board;
    private Group boardGroup;
    private Group marblesGroup;
    private Group boardDebugGroup;
    private Polygon[][] hexagons = new Polygon[11][11];
    private Sprite[][] marbles = new Sprite[11][11];
    private Sprite[][] tempMarbles = new Sprite[11][11];
    private Polygon[][] staticMarbles = new Polygon[11][11];
    private Group[] playersHUD = new Group[2];
    private Text[] playerPoints = new Text[2];

    private int[][] marble_x = new int[11][11];
    private int[][] marble_y = new int[11][11];

    private double kula_scale = 0.42;
    // Needed to add this because some people had bug rendering hexagons.

    private Polygon createHex(GraphicEntityModule graphics, double radius, int centerX, int centerY, int row, int d,
            Group group) {
        Polygon hex = graphics.createPolygon();
        // Creates HexGrid
        int[] xs = new int[6];
        int[] ys = new int[6];
        for (int i = 0; i < 6; i++) {
            int x = (int) (radius * 1.75 * row + centerX + radius * Math.cos((d + i * 2) * Math.PI / 6D));
            int y = (int) (centerY + radius * Math.sin((d + i * 2) * Math.PI / 6D));
            xs[i] = x;
            ys[i] = y;
            hex.addPoint(x, y);
        }
        hex.setFillColor(0xE7BA7B).setLineWidth(5).setLineColor(0x000000).setZIndex(0);

        if (group != null) {
            group.add(graphics.createLine().setX(xs[0]).setY(ys[0]).setX2(xs[5]).setY2(ys[5]).setLineColor(0x000000)
                    .setZIndex(1).setLineWidth(5));
        }

        return hex;
    };

    public BoardView(Board board, GraphicEntityModule graphics, TooltipModule tooltips, ToggleModule toggle) {
        this.board = board;
        this.graphics = graphics;

        boardGroup = graphics.createGroup();
        boardDebugGroup = graphics.createGroup();
        playersHUD[0] = graphics.createGroup();
        playersHUD[1] = graphics.createGroup();
        playersHUD[0].setZIndex(2).setX(100).setY(40);
        playersHUD[1].setZIndex(2).setX(1600).setY(750);
        marblesGroup = graphics.createGroup();
        marblesGroup.setZIndex(2);
        
        boardGroup.setZIndex(1);
        boardDebugGroup.setZIndex(1);
        Group texts = graphics.createGroup();

        // Background
        graphics.createRectangle().setWidth(WIDTH).setHeight(HEIGHT).setFillColor(0xababab).setZIndex(0);

        texts.setZIndex(2);

        double radius = 65;
        int centerX = 735;
        int centerY = 150;

        boardGroup.add(createHex(graphics, radius * 9, centerX + (int) (1.75 * radius * 2),
                centerY + (int) (radius * 1.5 * 4), 0, 0, boardGroup).setFillColor(0x6F2503));

        // Generates hex grid
        int h = 0, c = 0;
        for (int y = 0; y < 11; ++y) {
            c = 0;
            for (int x = 0; x < 11; ++x) {
                Integer player = board.getBoardValue(x, y);
                if (player == null) {
                    continue;
                }

                hexagons[x][y] = createHex(graphics, radius, centerX, centerY, c, 1, boardDebugGroup);
                staticMarbles[x][y] = createHex(graphics, radius, centerX, centerY, c, 1, null).setAlpha(0);
                boardDebugGroup.add(hexagons[x][y]);
                marblesGroup.add(staticMarbles[x][y]);
                tooltips.setTooltipText(staticMarbles[x][y], c + " " + h);

                boardGroup.add(graphics.createCircle().setX(centerX + (int) (radius * 1.75 * c)).setY(centerY)
                        .setRadius((int) (radius * 0.7)).setFillColor(0xAD694A));
                marble_x[x][y] = centerX + (int) (radius * 1.75 * c);
                marble_y[x][y] = centerY;
                        
                if (player != 0) {
                    paintSquare(x, y, player);

                    marbles[x][y] = graphics.createSprite();
                    if (player == 1) {
                        marbles[x][y].setImage("super_kula_biala.png");
                    } else {
                        marbles[x][y].setImage("super_kula_czarna.png");
                    }
                    
                    marbles[x][y].setX(centerX + (int) (radius * 1.75 * c)).setY(centerY).setAnchorX(0.5).setAnchorY(0.5).setScale(kula_scale);

                    marblesGroup.add(marbles[x][y]);
                }

                texts.add(graphics.createText(c + "  " + h).setX(centerX + (int) (radius * 1.75 * c)).setY(centerY)
                        .setAnchorX(0.5).setAnchorY(0.5).setFontSize(40));

                c += 1;
            }

            if (c == 0) {
                // null row
                continue;
            }

            if (h < 4) {
                centerX -= radius * 0.875;
                centerY += radius * 1.5;
            } else {
                centerX += radius * 0.875;
                centerY += radius * 1.5;
            }

            h += 1;
        }

        for (Player player : board.getPlayers()) {
            DrawPlayer(player);
        }

        toggle.displayOnToggleState(texts, "debugToggle", true);
        toggle.displayOnToggleState(boardGroup, "debugToggle", false);
        toggle.displayOnToggleState(marblesGroup, "debugToggle", false);
        toggle.displayOnToggleState(boardDebugGroup, "debugToggle", true);
    }

    public void paintSquare(int x, int y, int player) {
        if (hexagons[x][y] == null) {
            return;
        }
        
        if (player == 0) {
            hexagons[x][y].setFillColor(0xE7BA7B);
        } else if (player == 1) {
            hexagons[x][y].setFillColor(0xFFFFFF);
        } else if (player == 2) {
            hexagons[x][y].setFillColor(0x343434);
        }
    }

    private void changeMarblePosition(Sprite marble, int ex, int ey, int player) {
        player = 3 - player;
        if (hexagons[ex][ey] == null) {
            marble.setZIndex(5);

            if (player == 1) {
                marble.setAnchorX(0.5).setX(200).setY(40 + 200 + 50 + 120 * board.getPlayers().get(player - 1).getScore());
            } else {
                marble.setAnchorX(0.5).setX(1700).setY(800 - 120 * board.getPlayers().get(player - 1).getScore());
            }
        } else {
            marble.setX(marble_x[ex][ey]).setY(marble_y[ex][ey]);
        }
    }

    public void updateBoard(MoveLog movelog) {
        graphics.commitWorldState(0);

        int colors[][] = new int[11][11];
        
        for (MoveLogEntry move : movelog) {
            // System.out.println(String.format("Move log %d %d %d %d %d", move.startX, move.startY, move.endX, move.endY, move.playerID));

            colors[move.endX][move.endY] = move.playerID;
            paintSquare(move.endX, move.endY, move.playerID);
            
            if (colors[move.startX][move.startY] == 0) {
                paintSquare(move.startX, move.startY, 0);
            }

            changeMarblePosition(marbles[move.startX][move.startY], move.endX, move.endY, move.playerID);
        }

        graphics.commitWorldState(1);

        for (int x = 0; x < 11; x++) {
            for (int y = 0; y < 11; y++) {
                tempMarbles[x][y] = null;
            }
        }        

        for (MoveLogEntry move : movelog) {
            tempMarbles[move.endX][move.endY] = marbles[move.startX][move.startY];
            marbles[move.startX][move.startY] = null;
            changeMarblePosition(tempMarbles[move.endX][move.endY], move.endX, move.endY, move.playerID);
        }

        for (int x = 0; x < 11; x++) {
            for (int y = 0; y < 11; y++) {
                if(tempMarbles[x][y] != null) {
                    marbles[x][y] = tempMarbles[x][y];
                }
            }
        }

        for (int i = 0; i < 2; ++i) {
            playerPoints[i].setText(String.format("Score: %d", board.getPlayers().get(i).getScore()));
        }
    }

    public void DrawPlayer(Player player) {

        String name = player.getNicknameToken();
        int pid = player.getIndex();

        if(name.length() > 13) {
            name = name.substring(0, 13);
        }

        playersHUD[pid].add(graphics.createText(name)
            .setX(100)
            .setAnchorX(0.5)
            .setY(220)
            .setFontSize(40)
            .setFontWeight(Text.FontWeight.BOLD)
            .setFontFamily("Calibri")
            .setFillColor(player.getColorToken())
        );

        playersHUD[pid].add(graphics.createSprite()
            .setImage(player.getAvatarToken())
            .setX(0)
            .setY(0)
            .setBaseWidth(200)
            .setBaseHeight(200)
        );

        playerPoints[pid] = graphics.createText(String.format("Score: %d", player.getScore()))
            .setAnchorX(0.5)
            .setX(100)
            .setY(270)
            .setFontSize(40)
            .setFontWeight(Text.FontWeight.BOLD)
            .setFontFamily("Calibri");
        
        playersHUD[pid].add(playerPoints[pid]);
    }
}
