package org.artisanlogiciel.games.maze.gui;

import org.artisanlogiciel.games.maze.Brick;
import org.artisanlogiciel.games.maze.LabyModel;
import org.artisanlogiciel.games.maze.Position;
import org.artisanlogiciel.games.maze.solve.DirectionPosition;

import java.awt.*;

public class MazeCellParameters {
    int offsetX; // x offset of upper corner left in pixels
    int offsetY; // y offset of upper corner left in pixers

    int mapWidth;
    int mapHeight;

    // computed see adaptTo
    double width; // width of one cell in pixels
    double height; // height of one cell in pixels

    public MazeCellParameters(int mapw, int maph, int W, int H, int x, int y) {
        mapWidth = mapw;
        mapHeight = maph;
        offsetX = x;
        offsetY = y;
        adaptTo(W,H);
    }

    public void resetMazeWidthHeight(int mapw, int maph) {
        mapWidth = mapw;
        mapHeight = maph;
    }

    public void adaptTo(double W, double H) {
        double w = (W - offsetX) / mapWidth;
        double h = (H - offsetY) / mapHeight;
        if (w < 5)
            w = 5;
        if (h < 5)
            h = 5;
        setCellSize(w, h);
    }

    // for a given (x,y) pixel return cell position.
    Position toMazeCoordinates(int x, int y) {
        int pX = (int) ((double) (x - getOffsetX()) / getWidth());
        int pY = (int) ((double) (y - getOffsetY()) / getHeight());
        return new Position(pX, pY);
    }

    public void setCellSize(double w, double h) {
        width = w;
        height = h;
    }

    public double getWidth() {
        return width;
    }

    public double getHeight() {
        return height;
    }

    public int getOffsetX() {
        return offsetX;
    }

    public int getOffsetY() {
        return offsetY;
    }

    public Dimension getDimension() {
        return new Dimension(offsetX + (int) (mapWidth * width),
                offsetY + (int) (mapHeight * height));
    }

    public Color getGreyedColor(Color color, int greylevel)
    {
        Color greyedColor = new Color(
                Math.max(0,color.getRed() - greylevel),
                Math.max(0,color.getGreen() - greylevel),
                Math.max(0,color.getBlue() - greylevel));
        return greyedColor;
    }
    public void drawBackground(Graphics g, int pX, int pY, short walls) {
        int x = offsetX + (int) (pX * width);
        int y = offsetY + (int) (pY * height);
        Color savecolor = g.getColor();
        int greylevel = walls << 2;
        g.setColor(getGreyedColor(savecolor,greylevel));
        //g.fillRect(x+1,y+1,((int)width) -1,((int)height) - 1);
        g.fillRect(x,y,((int)width),((int)height));
    }
    public void drawWalls(Graphics g, int pX, int pY, short walls) {
        int x = offsetX + (int) (pX * width);
        int y = offsetY + (int) (pY * height);
        if ((pY == 0) && ((walls & Brick.UP) == Brick.UP))
            g.drawLine(x, y, x + (int) width, y);
        if ((walls & Brick.DOWN) == Brick.DOWN)
            g.drawLine(x, y + (int) height, x + (int) width, y + (int) height);
        if ((walls & Brick.RIGHT) == Brick.RIGHT)
            g.drawLine(x + (int) width, y, x + (int) width, y + (int) height);
        if ((pX == 0) && ((walls & Brick.LEFT) == Brick.LEFT))
            g.drawLine(x, y, x, y + (int) height);
    }

    public void drawPath(Graphics g, DirectionPosition dp, int pX, int pY, int mX, int mY) {
        if (dp != null) {
            Position dot = dp.getPosition();
            if ((dot.getX() >= pX) && (dot.getY() >= pY) && (dot.getX() < mX) && (dot.getY() < mY)) {
                int x = offsetX + (int) (dot.getX() * width);
                int y = offsetY + (int) (dot.getY() * height);
                short path = dp.getDirection();
                int xm = x + (int) (width / 2);
                int ym = y + (int) (height / 2);
                if ((path & LabyModel.HORIZONTAL) == LabyModel.HORIZONTAL) {
                    if ((path & LabyModel.POSITIVE) == LabyModel.POSITIVE) {
                        g.drawLine(xm, ym, x + (int) width, ym);
                        g.drawLine(xm, ym + (int) (height / 4), x + (int) width, ym);
                    }
                    // LEFT /_
                    if ((path & LabyModel.NEGATIVE) == LabyModel.NEGATIVE) {
                        g.drawLine(x, ym, xm, ym);
                        g.drawLine(x, ym, xm, ym - (int) (height / 4));
                    }
                }
                if ((path & LabyModel.VERTICAL) == LabyModel.VERTICAL) {
                    if ((path & LabyModel.POSITIVE) == LabyModel.POSITIVE) {
                        g.drawLine(xm, ym, xm, y + (int) height);
                        g.drawLine(xm - (int) (width / 4), ym, xm, y + (int) height);
                    }
                    // UP |\
                    if ((path & LabyModel.NEGATIVE) == LabyModel.NEGATIVE) {
                        g.drawLine(xm, ym, xm, y);
                        g.drawLine(xm + (int) (width / 4), ym, xm, y);
                    }
                }
            }
        }
    }

    public void drawDot(Graphics g, Position dot, int pX, int pY, int mX, int mY) {
        double radius = (height > width) ? width : height;
        int a = (int) (radius / 4);
        if ((dot.getX() >= pX) && (dot.getY() >= pY) && (dot.getX() < mX) && (dot.getY() < mY)) {
            int x = offsetX + (int) (dot.getX() * width);
            int y = offsetY + (int) (dot.getY() * height);
            int r2 = (int) ((radius * 3) / 4);
            g.drawOval(x + 1, y + 1, r2, r2);
            // g.drawLine(x+a,y+a,x+width-a,y+height-a);
            // g.drawLine(x+a,y+height-a,x+width-a,y+a);

        } else {
            int x = offsetX + (int) (pX * width);
            int y = offsetY + (int) (pY * height);
            g.drawLine(x + 1, y + 1, x + (int) width - 1, y + (int) height - 1);
        }
    }

}
