import os
from PIL import Image, ImageFilter
from defines import *
from layergen import *
from log import *

# -------------------------------------------------------------------
# ORTHOGRAPHIC
# Your personal aerial satellite. Always on. At any altitude.*
# Developed by MarStrMind
# License: Open Software License 3.0
# Up to date version always on marstr.online
# -------------------------------------------------------------------
# photogen.py
# The class that generates the photo tiles from previous layers,
# in their correct order.
# -------------------------------------------------------------------


class mstr_photogen:

    # Initializer doesn't need much
    def __init__ (self, lat, lng, ty, tx, maxlat, maxlng):
        self._lat = lat
        self._lng = lng
        self._ty = ty
        self._tx = tx
        self._maxlatlng = [ maxlat, maxlng ]
        # Define layer size depending on what is wanted
        self._imgsize = 0
        if mstr_photores == 2048: self._imgsize = 3000
        if mstr_photores == 4096: self._imgsize = 6000
        # Empty image where everything goes into
        self._tile = Image.new("RGBA", (self._imgsize, self._imgsize))
        mstr_msg("photogen", "Photogen initialized")

    
    # This puts it all together. Bonus: AND saves it.
    def genphoto(self):
        # Template for the file name which is always the same
        root_filename = mstr_datafolder + "/_cache/" + str(self._lat) + "-" + str(self._ty) + "_" + str(self._lng) + "-" + str(self._tx) + "_"

        # First, we walk through all layers and blend them on top of each other, in order
        mstr_msg("photogen", "Merging layers")

        for l in mstr_ortho_layers:
            if os.path.isfile(root_filename + l[0] + "-" + l[1] + "_layer.png"):
                # Need to divert in case we have shadows
                if mstr_shadow_enabled == True:
                    if os.path.isfile(root_filename + l[0] + "-" + l[1] + "_layer_shadow.png"):
                        sn = root_filename + l[0] + "-" + l[1] + "_layer_shadow.png"
                        s_layer = Image.open(sn)
                        self._tile.alpha_composite(s_layer)
                # Complete the file name based on the template
                fn = root_filename + l[0] + "-" + l[1] + "_layer.png"
                # Open the layer
                layer = Image.open(fn)
                # Converge the layer with this image
                self._tile.alpha_composite(layer)

        # When we have run through this loop, we will end up with a sandwiched
        # image of all the other images, in their correct order.
        # However, since I have discovered that some areas in OSM simply do not
        # have any tag or information, it is possible that the final image will
        # have empty, alpha-transparent patches.
        # For this reason we need to check against these and fix that.
        
        # First, we will check if there is something to fix:
        emptyspace = self.checkForEmptySpace()
        mstr_msg("photogen", "Checked for empty patches")

        # If this check comes back as true, we need to perform
        # aforementioned fix:
        if emptyspace == True:
            # Choose a suitable layer type
            lt = [6,14,17]
            pick = randrange(0,len(lt)-1)
            ltp = lt[pick]
            tag   = mstr_ortho_layers[ltp][0]
            value = mstr_ortho_layers[ltp][1]

            mstr_msg("photogen", "Patching empty space")
            self.buildCompletionMask()

            # Generate the layer as if it were part of the OSM data
            lg = mstr_layergen(tag, value, self._lat, self._ty, self._lng, self._tx, False, is_completion=True)
            lg.set_max_latlng_tile(self._maxlatlng)
            lg.genlayer()

            # Load the image
            completion = Image.open(root_filename + "tile-completion_layer.png")

            # Merge the images
            completion.alpha_composite(self._tile)

            # Make this the real one
            self._tile = completion


        # We are now in posession of the final image.

        # Scale to correct size.
        self._tile = self._tile.resize((mstr_photores, mstr_photores), Image.Resampling.BILINEAR)
        
        # This we can save accordingly.
        self._tile.convert('RGB').save(mstr_datafolder + "Tiles/" + str(self._lat) + "_" + str(self._lng) + "/textures/" + str(self._ty) + "_" + str(self._tx) + ".jpg", format='JPEG', subsampling=0, quality=100)


    # This checks the final image for empty patches. Should one be
    # found, we will generate something to fill the gap. If this is
    # the case, we will also note this in the database for the tile,
    # under the special tag and value "tile", "completion". The same
    # conditions apply for edge testing and so on.
    def checkForEmptySpace(self):
        empty = False

        # Load photo
        layer_pix = self._tile.load() 
        
        # Scan!
        for y in range(self._tile.width-1):
            for x in range(self._tile.height-1):
                p = layer_pix[x,y]
                if p[3] < 255: # <- Check for empty or non-complete alpha
                    empty = True
                    break

        # Tell about findings
        return empty
    

    # This returns a mask of the empty space to cover, should there be any
    def buildCompletionMask(self):
        mask = Image.new("RGBA", (self._imgsize, self._imgsize))
        mask_pix = mask.load()

        # Load photo
        layer_pix = self._tile.load() 
        
        # Scan!
        for y in range(self._tile.width-1):
            for x in range(self._tile.height-1):
                p = layer_pix[x,y]
                if p[3] < 255: # <- Check for empty or non-complete alpha
                    mask_pix[x,y] = (0,0,0,255)
        # We do not apply any blur or other effects here - we only want the
        # exact pixel positions.

        mask.save( mstr_datafolder + "_cache/" + str(self._lat) + "-" + str(self._ty) + "_" + str(self._lng) + "-" + str(self._tx) + "_tile-completion.png" )
        mstr_msg("photogen", "Generated and saved empty space mask")