from siege.log import Log
from siege.worldgen import Terraform
from siege.world.realm import Layer
from siege.util import Sizes


def saveWorldImage(game, world, realm, undergroundThreshold, biomes=None):
    worldImage = paintWorldImage(game, world, realm, undergroundThreshold, biomes)
    if worldImage:
        Log.info("Saving world image...")
        worldImage.save("map.png")
    else:
        Log.info("Couldn't generate world image.")


def paintWorldImage(game, world, realm, undergroundThreshold, biomes=None):
    try:
        import sys
        sys.path.append(r'/Library/Python/2.7/site-packages')
        sys.path.append(r'/Library/Python/2.7/site-packages/PIL')
        sys.path.append(r'C:\Python27\lib\site-packages')
        sys.path.append(r'C:\Python27\lib\site-packages\PIL')
        from PIL import Image
        worldImage = Image.new('RGBA', (realm.size.tileWidth, realm.size.tileHeight))
    except Exception as e:
        Log.info("Couldn't import PIL; bailing out.")
        return None

    content = lambda content: game.content.get(content).id
    #Setup the map of tile id to RGB
    tileColors = {
        content('dirt'): ((100, 80, 60, 255), (80, 60, 40, 255)),
        content('dirt_grass'): ((66, 100, 37, 255), (66, 100, 37, 255)),
        content('pots'): ((255, 0, 255, 255), (255, 0, 255, 255)),
        content('foliage'): ((66, 100, 37, 255), (66, 100, 37, 2515)),
        content('vine_bases'): ((66, 100, 37, 255), (66, 100, 37, 255)),
        content('vine_mids'): ((66, 100, 37, 255), (66, 100, 37, 255)),
        content('vine_ends'): ((66, 100, 37, 255), (66, 100, 37, 255)),
        content('sand'): ((158, 128, 87, 255), (120, 108, 70, 255)),
        content('snow'): ((214, 219, 223, 255), (214, 219, 223, 255)),
        content('soot'): ((120, 120, 120, 255), (120, 120, 120, 255)),
        content('stone'): ((75, 68, 58, 255), (60, 54, 48, 255)),
        content('clay'): ((107, 54, 42, 255), (107, 54, 42, 255)),
        content('copper_ore'): ((182, 107, 65, 255), (182, 107, 65, 255)),
        content('iron_ore'): ((98, 103, 110, 255), (98, 103, 110, 255)),
        content('silver_ore'): ((152, 143, 132, 255), (152, 143, 132, 255)),
        content('gold'): ((141, 113, 50, 255), (141, 113, 50, 255)),
        content('osmium'): ((64, 74, 112, 255), (64, 74, 112, 255)),
        content('diamond'): ((218, 217, 215, 255), (218, 217, 215, 255)),
        content('sapphire'): ((92, 145, 231, 255), (92, 145, 231, 255)),
        content('ruby'): ((230, 116, 120, 255), (230, 116, 120, 255)),
        content('gold_brick'): ((200, 170, 50, 255), (200, 170, 50, 255)),
    }

    data = [(200, 234, 241, 255)] * realm.size.tileWidth * realm.size.tileHeight
    try:
        Log.info("Populating pixel data of map.")
        Terraform.populateMapData(realm, data, tileColors)
        Terraform.populateMapAutomataData(realm, data)
        Log.info("Finished populating pixel data.")
    except KeyError as e:
        Log.info('Missing a tile color: %s' % e.message)
        Log.info('Missing a tile color: %s' % (game.content.get(int(e.message)).path,))
        raise
    worldImage.putdata(data)
    Log.info("Finished putdata")
    pixels = worldImage.load()
    Log.info("Loaded pixels.")

    def writePixel(x, y, color):
        if y < 0 or y >= realm.size.tileHeight:
            return
        if x < 0:
            x += realm.size.tileWidth
        elif x >= realm.size.tileWidth:
            x -= realm.size.tileWidth
        try:
            pixels[x, y] = color
        except IndexError:
            Log.info("Failed to writePixel at ({}, {})".format(x, y))
            raise

    # draw a line at the underground level
    #for x in range(0, realm.size.tileWidth):
    #    writePixel(x, world.groundLevel, (0, 0, 0, 255))
    for x in range(0, realm.size.tileWidth):
        writePixel(x, undergroundThreshold[x], (0, 0, 0, 255))

    if biomes:
        firstBiomeColor = (0, 0, 0)
        biomeColor = firstBiomeColor
        for biome in biomes:
            for y in range(0, realm.size.tileHeight):
                writePixel(biome.area.x, y, biomeColor)
            biomeColor = (127, 127, 127, 255)

    for layer in [Layer.Back, Layer.Item, Layer.Active]:
        for entity in realm.layers[layer].getAll():
            if entity.getName() == "Oak Tree":
                stage = entity.organic.organic.stage
                position = entity.getPosition()
                if stage == 0:
                    x = int(position.x / Sizes.TILE)
                    y = int(position.y / Sizes.TILE)
                    writePixel(x, y, (105, 129, 24, 255))
                else:
                    xStart = int(position.x / Sizes.TILE)
                    if position.x % Sizes.TILE < Sizes.TILE / 2:
                        xStart -= 1
                    yStart = int(position.y / Sizes.TILE)
                    for i in xrange(0, stage + 1):
                        for x in xrange(xStart, xStart + 2):
                            for y in xrange(yStart - 2, yStart):
                                if x < realm.size.tileWidth and x >= 0 and y < realm.size.tileHeight and y >= 0:
                                    writePixel(x, y, (135, 89, 58, 255))
                        yStart -= 2
                    xStart -= 1
                    for x in xrange(xStart, xStart + 4):
                        for y in xrange(yStart - 4, yStart):
                            if x < realm.size.tileWidth and x >= 0 and y < realm.size.tileHeight and y >= 0:
                                writePixel(x, y, (105, 129, 24, 255))
            elif entity.getName() == "Zebra Tree":
                stage = entity.organic.organic.stage
                position = entity.getPosition()
                if stage == 0:
                    x = int(position.x / Sizes.TILE)
                    y = int(position.y / Sizes.TILE)
                    writePixel(x, y, (134, 51, 11))
                else:
                    xStart = int(position.x / Sizes.TILE)
                    yStart = int(position.y / Sizes.TILE) - 1
                    for i in xrange(0, stage + 1):
                        if i % 2 == 0:
                            writePixel(xStart, yStart, (90, 64, 44, 255))
                        else:
                            writePixel(xStart, yStart, (197, 188, 178, 255))
                        yStart -= 1
                    xStart -= 1
                    for x in xrange(xStart, xStart + 3):
                        for y in xrange(yStart - 3, yStart + 1):
                            if x < realm.size.tileWidth and x >= 0 and y < realm.size.tileHeight and y >= 0:
                                writePixel(x, y, (134, 51, 11, 255))
            elif entity.getName() == "Mushroom Tree":
                stage = entity.organic.organic.stage
                position = entity.getPosition()
                if stage == 0:
                    x = int(position.x / Sizes.TILE)
                    y = int(position.y / Sizes.TILE)
                    writePixel(x, y, (61, 170, 193, 255))
                else:
                    xStart = int(position.x / Sizes.TILE)
                    yStart = int(position.y / Sizes.TILE) - 1
                    for i in xrange(0, stage + 1):
                        writePixel(xStart, yStart, (110, 100, 98, 255))
                        yStart -= 1
                    xStart -= 1
                    for x in xrange(xStart, xStart + 2):
                        for y in xrange(yStart - 1, yStart + 1):
                            if x < realm.size.tileWidth and x >= 0 and y < realm.size.tileHeight and y >= 0:
                                writePixel(x, y, (61, 170, 193, 255))
            elif "Chest" in entity.getName():
                position = entity.getPosition()
                x = int(position.x / Sizes.TILE)
                y = int(position.y / Sizes.TILE) + 1
                if y < realm.size.tileHeight:
                    writePixel(x, y, (244, 239, 104, 255))

            elif "Stalagmite" == entity.getName():
                stage = entity.organic.organic.stageIndex
                position = entity.getPosition()
                x = int(position.x / Sizes.TILE)
                y = int(position.y / Sizes.TILE) - 1

                writePixel(x, y, (155, 155, 155, 255))
                if stage > 0:
                    writePixel(x, y - 1, (130, 130, 130, 255))
                if stage > 1:
                    writePixel(x, y - 2, (105, 105, 105, 255))

            elif "Stalactite" == entity.getName():
                stage = entity.organic.organic.stageIndex
                position = entity.getPosition()
                x = int(position.x / Sizes.TILE)
                y = int(position.y / Sizes.TILE)

                writePixel(x, y, (155, 155, 155, 255))
                if stage > 0:
                    writePixel(x, y + 1, (130, 130, 130, 255))
                if stage > 1:
                    writePixel(x, y + 2, (105, 105, 105, 255))

            elif "Torch" in entity.getName():
                position = entity.getPosition()
                x = int(position.x / Sizes.TILE)
                y = int(position.y / Sizes.TILE) + 1
                writePixel(x, y, (180, 50, 30, 255))
                writePixel(x, y - 1, (180, 50, 30, 255))

            elif "Spawner" in entity.getName():
                position = entity.getPosition()
                x = int(position.x / Sizes.TILE)
                y = int(position.y / Sizes.TILE) + 1
                writePixel(x, y, (129, 42, 171, 255))
                writePixel(x, y - 1, (129, 42, 171, 255))
                writePixel(x + 1, y, (129, 42, 171, 255))
                writePixel(x + 1, y - 1, (129, 42, 171, 255))

            elif "Way Crystal" in entity.getName():
                position = entity.getPosition()
                centerX = int(position.x / Sizes.TILE)
                centerY = int(position.y / Sizes.TILE)
                for x in range(centerX - 2, centerX + 3):
                    for y in range(centerY - 2, centerY + 3):
                        writePixel(x, y, (0, 0, 0, 255))
                for x in range(centerX - 1, centerX + 2):
                    for y in range(centerY - 1, centerY + 2):
                        writePixel(x, y, (191, 50, 255, 255))
                writePixel(centerX, centerY, (255, 255, 255, 255))

    return worldImage


def paintRect(worldImage, rect):
    pixels = worldImage.load()
    for x in range(rect.x, rect.x + rect.width + 1):
        for y in range(rect.y, rect.y + rect.height + 1):
            if x in [rect.x, rect.x + rect.width] or y in [rect.y, rect.y + rect.height]:
                pixels[x, y] = (0, 0, 0)

    return worldImage
