from functools import partial

from core.terraform.helper import plantOrganicAction, placeTiles
from core.terraform.stamps import createStampColor, loadStamps, SurfaceStamp

from siege import game
from siege.util import RangeUint, Vector
from siege.worldgen import Biome, ColorStamp, FillMode
from siege.world.realm import Layer


class MountainBiome(Biome):
    def __init__(self):
        Biome.__init__(self)
        self.name = "Mountain"
        self.layer = "surface"
        self.frequency = 10
        self.width = RangeUint(10, 12)
        self.height = RangeUint(50, 80)
        self.heightTolerance = 5
        self.widthIncrement = 32
        self.groundId = game.content.get('dirt').id
        self.wallId = self.groundId
        self.sky = 'mods/core/environment/sky.png'
        self.back1.scroll = Vector(0.5, 0.1)
        self.back2.images.append('mods/core/environment/mountains/bg2.png')
        self.back2.offset = -175
        self.back2.scroll = Vector(0.3, 0.075)
        self.back3.images.append('mods/core/environment/mountains/bg3.png')
        self.back3.offset = -250
        self.back3.scroll = Vector(0.1, 0.05)

        self._generateStamps()

    def getOccurrences(self, realmSize):
        return RangeUint(1, 9999)

    def reset(self, area):
        # "reset" the width-tracking for whether we want incline or decline stamps
        self._originalSpace = None

    def isCompatible(self, biome):
        return biome.name not in ["Desert", "Mountain"]

    def getStamps(self, remainingSpace):
        if not self._originalSpace:
            self._originalSpace = remainingSpace
        if remainingSpace > self._originalSpace / 2:
            return self._inclineStamps
        else:
            return self._declineStamps

    def getRules(self):
        tileRules = {}
        tileRules[createStampColor(100, 80, 60)] = (self.groundId, 0)
        tileRules[createStampColor(80, 60, 40)] = (self.groundId, self.wallId)
        tileRules[createStampColor(154, 126, 98)] = (0, self.wallId)
        tileRules[createStampColor(48, 141, 255)] = (self.groundId, self.wallId)  # This is to fill cave entrances with with solid tile
        tileRules[createStampColor(214, 219, 223)] = (game.content.get('snow').id, 0)
        return tileRules

    def getActions(self, biomeData):
        frequency = 1 / 10000.0
        actions = []
        actions.append(partial(placeTiles, Layer.Ground, '', 4 * frequency, (2, 5), (2, 5), (0.25, 1.0), FillMode.SOLID_ONLY, "holes"))
        actions.append(partial(placeTiles, Layer.Ground, '', 3 * frequency, (5, 10), (5, 10), (0.0, 1.0), FillMode.SOLID_ONLY, "holes"))
        actions.append(partial(placeTiles, Layer.WallAndGround, 'stone', 10 * frequency, (5, 10), (5, 10), (0.0, 1.0), FillMode.SOLID_ONLY, "tile_small"))
        actions.append(partial(placeTiles, Layer.WallAndGround, 'stone', 5 * frequency, (8, 15), (8, 15), (0.0, 1.0), FillMode.SOLID_ONLY, "tile_medium"))
        actions.append(partial(placeTiles, Layer.Ground, 'copper_ore', 5 * frequency, (2, 5), (2, 5), (0.2, 1.0), FillMode.SOLID_ONLY, "tile_small"))
        actions.append(partial(placeTiles, Layer.Ground, 'copper_ore', 3 * frequency, (4, 5), (4, 5), (0.6, 1.0), FillMode.SOLID_ONLY, "tile_medium"))
        actions.append(partial(placeTiles, Layer.Ground, 'iron_ore', 4 * frequency, (2, 6), (2, 6), (0.7, 1.0), FillMode.SOLID_ONLY, "tile_small"))
        return actions

    def getPostActions(self, biomeData):
        actions = []
        actions.append(partial(plantOrganicAction, 'pine_tree', Layer.Back, (20, 30), True, False))
        actions.append(partial(plantOrganicAction, 'dead_tree', Layer.Back, (10, 15), True, False))
        return actions

    def _generateStamps(self):
        stamps = loadStamps('mountains', False)

        self._inclineStamps = []
        self._declineStamps = []

        for stamp in stamps:
            flipped = ColorStamp(stamp.image, False)
            flipped.setForceFlipX(True)

            wrap = SurfaceStamp(stamp)

            if wrap.isIncline():
                self._inclineStamps.append(stamp)
                self._declineStamps.append(flipped)
            else:
                self._declineStamps.append(stamp)
                self._inclineStamps.append(flipped)
