import math

from PIL import Image, ImageDraw, ImageFont
from funcs import logThis

# Defining all the variables
CANVAS_WIDTH  = 2400
CANVAS_HEIGHT = 1800
SIDELENGTH = 75
X_OFFSET = CANVAS_WIDTH/2 - 8*math.sqrt(3)*SIDELENGTH # The offsets centers the board in the picture
Y_OFFSET = CANVAS_HEIGHT/2 - 8*SIDELENGTH # The offsets are the coordinates of the upperleft point in the upperleftmost hexagon
HEXAGONWIDTH = math.sqrt(3) * SIDELENGTH # the whole width of one hexagon
HEXAGONHEIGHT = 1.5 * SIDELENGTH # not really the entire height, but the height difference between two layers
FONTSIZE = 45
TEXTCOLOR = (0,0,0)
fnt = ImageFont.truetype('resources/futura-bold.ttf', FONTSIZE)

LINETHICKNESS = 15
HEXTHICKNESS = 6 # This is half the width of the background lining between every hex
X_THICKNESS = HEXTHICKNESS * math.cos(math.pi/6)
Y_THICKNESS = HEXTHICKNESS * math.sin(math.pi/6)
BACKGROUND_COLOR = (230,230,230)
BETWEEN_COLOR = (231,231,231)
BLANK_COLOR = "lightgrey"
PIECECOLOR = {1:(237,41,57),2:(0,165,255),0:BLANK_COLOR} # player1 is red, player2 is blue
BOARDCOORDINATES = [ [(X_OFFSET + HEXAGONWIDTH*(column + row/2),Y_OFFSET + HEXAGONHEIGHT*row) for column in range(11)] for row in range(11)] # These are the coordinates for the upperleft corner of every hex
COLHEXTHICKNESS = 4 # When placing a hex, it is a little bigger than the underlying hex in the background (4 < 6)
COLX_THICKNESS = COLHEXTHICKNESS * math.cos(math.pi/6)
COLY_THICKNESS = COLHEXTHICKNESS * math.sin(math.pi/6)
# The Name display things:
NAMESIZE = 60
NAME_fnt = ImageFont.truetype('resources/futura-bold.ttf', NAMESIZE)
X_NAME = {1:175, 2:CANVAS_WIDTH-100}
Y_NAME = {1:CANVAS_HEIGHT-150, 2:150}
NAMEHEXPADDING = 90
SMOL_WIDTH = HEXAGONWIDTH * 0.6
SMOL_SIDELENGTH = SIDELENGTH * 0.6

class DrawHex():
    def __init__(self,bot):
        self.bot = bot

    def drawBoard(self, channel):
        logThis("Drawing empty Hex board")

        # Creates the empty image
        im = Image.new('RGB', size=(CANVAS_WIDTH, CANVAS_HEIGHT),color = BACKGROUND_COLOR)
        # 'd' is a shortcut to drawing on the image
        d = ImageDraw.Draw(im,"RGBA")

        # Drawing all the hexagons
        for column in BOARDCOORDINATES:
            for startingPoint in column:
                x = startingPoint[0]
                y = startingPoint[1]
                d.polygon([
                    (x,                  y),
                    (x+HEXAGONWIDTH/2,   y-0.5*SIDELENGTH),
                    (x+HEXAGONWIDTH,     y),
                    (x+HEXAGONWIDTH,     y+SIDELENGTH),
                    (x+HEXAGONWIDTH/2,   y+1.5*SIDELENGTH),
                    (x,                  y+SIDELENGTH),
                ],fill = BETWEEN_COLOR)
                d.polygon([
                    (x+X_THICKNESS,                y + Y_THICKNESS),
                    (x+HEXAGONWIDTH/2,             y-0.5*SIDELENGTH + HEXTHICKNESS),
                    (x+HEXAGONWIDTH-X_THICKNESS,   y + Y_THICKNESS),
                    (x+HEXAGONWIDTH-X_THICKNESS,   y+SIDELENGTH - Y_THICKNESS),
                    (x+HEXAGONWIDTH/2,             y+1.5*SIDELENGTH - HEXTHICKNESS),
                    (x+X_THICKNESS,                y+SIDELENGTH - Y_THICKNESS),
                ],fill = BLANK_COLOR)

        # Draw color on the outside of the board
        # Top line, red
        d.line(sum((sum([(point[0],point[1],point[0]+HEXAGONWIDTH/2,point[1]-HEXAGONHEIGHT+SIDELENGTH) for point in BOARDCOORDINATES[0]],()),(BOARDCOORDINATES[0][10][0]+HEXAGONWIDTH*3/4,BOARDCOORDINATES[0][10][1]-SIDELENGTH/4)),()),
                fill = PIECECOLOR[1],width = LINETHICKNESS)
        # Bottom line, red
        d.line(sum(((BOARDCOORDINATES[10][0][0]+HEXAGONWIDTH/4,BOARDCOORDINATES[10][0][1]+SIDELENGTH*5/4),sum([(point[0]+HEXAGONWIDTH/2,point[1]+HEXAGONHEIGHT,point[0]+HEXAGONWIDTH,point[1]+SIDELENGTH) for point in BOARDCOORDINATES[10]],())),()),
                fill = PIECECOLOR[1],width = LINETHICKNESS)
        # Left line, blue
        d.line(sum((sum([(row[0][0],row[0][1],row[0][0],row[0][1]+SIDELENGTH) for row in BOARDCOORDINATES],()),(BOARDCOORDINATES[10][0][0]+HEXAGONWIDTH/4,BOARDCOORDINATES[10][0][1]+SIDELENGTH*5/4)),()),
                fill = PIECECOLOR[2],width = LINETHICKNESS)
        # Right line, blue
        d.line(sum(((BOARDCOORDINATES[0][10][0]+HEXAGONWIDTH*3/4,BOARDCOORDINATES[0][10][1]-SIDELENGTH/4),sum([(row[10][0]+HEXAGONWIDTH,row[10][1],row[10][0]+HEXAGONWIDTH,row[10][1]+SIDELENGTH) for row in BOARDCOORDINATES],())),()),
                fill = PIECECOLOR[2],width = LINETHICKNESS)

        # Writes "abc..", "123.." on the columns and rows
        for i in range(11):
            # Top letters
            d.text( (X_OFFSET + HEXAGONWIDTH*i, Y_OFFSET-66) , "ABCDEFGHIJK"[i], font=fnt, fill=TEXTCOLOR)
            # Bottom letters
            d.text( (X_OFFSET + HEXAGONWIDTH*(i+11.5/2), Y_OFFSET - 15 + 11*HEXAGONHEIGHT) , "ABCDEFGHIJK"[i], font=fnt, fill=TEXTCOLOR)
            # Left numbers
            d.multiline_text( (X_OFFSET + HEXAGONWIDTH*i/2 - 72 -4*(i>8), Y_OFFSET + 18 + i*HEXAGONHEIGHT) , str(i+1), font=fnt, fill=TEXTCOLOR, align="right")
            # Right numbers
            d.text( (X_OFFSET + HEXAGONWIDTH*(i/2+11) + 30 , Y_OFFSET + 6 + i*HEXAGONHEIGHT) , str(i+1), font=fnt, fill=TEXTCOLOR)

        # Write player names and color
        game = self.bot.database["hex games"].find_one({"_id":channel})

        for p in [1,2]:
            playername = self.bot.funcs.getName(game["players"][p-1])
            # Draw name
            x = X_NAME[p]
            x -= NAME_fnt.getsize(playername)[0] if p==2 else 0 # player2's name is right-aligned
            y = Y_NAME[p]
            d.text((x,y),playername, font=NAME_fnt, fill = TEXTCOLOR)
            # Draw a half-size Hexagon to indicate the player's color
            x -= NAMEHEXPADDING # To the left of both names
            d.polygon([
                (x,                  y),
                (x+SMOL_WIDTH/2,     y-SMOL_SIDELENGTH/2),
                (x+SMOL_WIDTH,       y),
                (x+SMOL_WIDTH,       y+SMOL_SIDELENGTH),
                (x+SMOL_WIDTH/2,     y+SMOL_SIDELENGTH*3/2),
                (x,                  y+SMOL_SIDELENGTH),
            ],fill = PIECECOLOR[p])

        im.save("resources/games/hexBoards/board"+channel+".png")




    def drawHexPlacement(self, channel,player,position):
        FILEPATH = "resources/games/hexBoards/board"+channel+".png"
        logThis("Drawing a newly placed hex. Filepath: "+FILEPATH)

        # Translates position
        # We don't need to error-check, because the position is already checked in placeOnHexBoard()
        position = position.lower()
        column = ord(position[0])-97   # ord() translates from letter to number
        row = int(position[1:])-1

        # Find the coordinates for the filled hex drawing
        hexCoords = [
            (BOARDCOORDINATES[row][column][0]+COLX_THICKNESS,              BOARDCOORDINATES[row][column][1] + COLY_THICKNESS),
            (BOARDCOORDINATES[row][column][0]+HEXAGONWIDTH/2,              BOARDCOORDINATES[row][column][1]-0.5*SIDELENGTH + COLHEXTHICKNESS),
            (BOARDCOORDINATES[row][column][0]+HEXAGONWIDTH-COLX_THICKNESS, BOARDCOORDINATES[row][column][1] + COLY_THICKNESS),
            (BOARDCOORDINATES[row][column][0]+HEXAGONWIDTH-COLX_THICKNESS, BOARDCOORDINATES[row][column][1]+SIDELENGTH - COLY_THICKNESS),
            (BOARDCOORDINATES[row][column][0]+HEXAGONWIDTH/2,              BOARDCOORDINATES[row][column][1]+1.5*SIDELENGTH - COLHEXTHICKNESS),
            (BOARDCOORDINATES[row][column][0]+COLX_THICKNESS,              BOARDCOORDINATES[row][column][1]+SIDELENGTH - COLY_THICKNESS),
            ]

        # Opens the image
        try:
            with Image.open(FILEPATH) as im:
                d = ImageDraw.Draw(im,"RGBA")
                # Draws the hex piece
                d.polygon(hexCoords,fill = PIECECOLOR[player], outline = BETWEEN_COLOR)

                # Save
                im.save(FILEPATH)
        except:
            logThis("Error drawing new hex on board (error code 1541")

    def drawSwap(self, channel):
        FILEPATH = "resources/games/hexBoards/board"+channel+".png"
        game = self.bot.database["hex games"].find_one({"_id":channel})
        # Opens the image
        try:
            with Image.open(FILEPATH) as im:
                d = ImageDraw.Draw(im,"RGBA")

                # Write player names and color
                for p in [1,2]:
                    playername = self.bot.funcs.getName(game["players"][p%2])

                    x = X_NAME[p]
                    x -= NAME_fnt.getsize(playername)[0] if p==2 else 0 # player2's name is right-aligned
                    y = Y_NAME[p]

                    # Draw a half-size Hexagon to indicate the player's color
                    x -= NAMEHEXPADDING # To the left of both names
                    d.polygon([
                        (x,                  y),
                        (x+SMOL_WIDTH/2,     y-SMOL_SIDELENGTH/2),
                        (x+SMOL_WIDTH,       y),
                        (x+SMOL_WIDTH,       y+SMOL_SIDELENGTH),
                        (x+SMOL_WIDTH/2,     y+SMOL_SIDELENGTH*3/2),
                        (x,                  y+SMOL_SIDELENGTH),
                    ],fill = PIECECOLOR[p % 2 + 1])

                # Save
                im.save(FILEPATH)
        except:
            logThis("Error drawing swap (error code 1542)")
