# -------------------------------------------------------------------
# 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
# -------------------------------------------------------------------
# tilegen.py
# Generates ZL16 tiles from the generated material, while checking on
# presence of airports, and keeping ZL18 tiles of the specified
# radius in defines.py. This also writes down the correspoding .ter
# files for X-Plane. Be careful: the unneeded ZL18 tiles will be
# removed.
# -------------------------------------------------------------------

from PIL import Image, ImageFilter
from log import *
from functions import *
from tiledb import *
import math
import os
import glob

class mstr_tilegen:
    # We only need some values. Also sets up connection to DB
    def __init__(self, lat, lng, vstep, max_lat, max_lng):
        self._lat    = lat
        self._lng    = lng
        self._vstep  = vstep
        self._maxlat = max_lat
        self._maxlng = max_lng
        # Connection to DB
        self._tiledb = mstr_tiledb(lat, lng)
        mstr_msg("tilegen", "Tilegen initialized")


    # To write down X-Plane .ter files, we will need to know the exact size
    # of the particular longitude we are in, as this value varies depending
    # on where you are on a sphere.
    # Returned values is in meters.
    # The current latitude is needed.
    def _findWidthOfLongitude(self, lat):
        dm = math.cos(math.radians(lat)) * 111.321 # <- 1 deg width at equator in km
        return round(dm * 1000, 3)


    # Generates the ZL16 tiles and stores them.
    # We generate ZL16 tiles first, then we check which tiles to keep near airports
    def genTiles(self):
        # The current lat and lng tile numbers
        cur_lat = 1
        cur_lng = 1

        # Actual starting coordinates for ZL16
        a_lat = self._lat + self._vstep * 2
        a_lng = self._lng + mstr_zl_18 * 2

        # Scaled res
        scaled_res = int(mstr_photores/4) # For example, 512 for a photo res of 2048

        # Find out how many steps we can walk in every direction
        steps_lat = int(math.ceil(self._maxlat/4))
        steps_lng = int(math.ceil(self._maxlng/4))
        mstr_msg("tilegen", "Latitude and longitude steps determined")

        # OK... so. Let's finish this.
        for lt in range(1, steps_lat):
            for ln in range(1, steps_lng):
                # Check if we need to do something
                if os.path.isfile(mstr_datafolder + "Tiles/" + str(self._lat) + "_" + str(self._lng) + "/textures/" + str(self._lat) + "-" + str(ln) + "_" + str(self._lng) + "-" + str(lt) + "_OG16.jpg") == False:

                    mstr_msg("tilegen", "Generating missing zoom level 16 ortho " + str(self._lat) + "-" + str(ln) + "_" + str(self._lng) + "-" + str(lt) + "_OG16.jpg")

                    # Find out which tiles to process
                    tiles = findZL16tiles(cur_lat, cur_lng)

                    # Generate the ZL16 image
                    zl16 = Image.new("RGB", (mstr_photores, mstr_photores))

                    # Walk through this array
                    xpos = 0
                    ypos = int(scaled_res*3)
                    for i in range(0, 3):
                        for j in range(0, 3):
                            # We may run into situations where ask for tiles that don't exist...
                            # Let's make sure we can continue
                            fpath = mstr_datafolder + "Tiles/" + str(self._lat) + "_" + str(self._lng) + "/textures/" + str(tiles[i][j][0]) + "_" + str(tiles[i][j][1]) + ".jpg"
                            if os.path.isfile( fpath ):
                                tlimg = Image.open(fpath)
                                tlimg = tlimg.resize((scaled_res,scaled_res), Image.Resampling.BILINEAR)
                                zl16.paste(tlimg, (xpos, ypos))
                            xpos = xpos + scaled_res
                        xpos = 0
                        ypos = ypos - scaled_res

                    # Now save this image
                    zl16.save(mstr_datafolder + "Tiles/" + str(self._lat) + "_" + str(self._lng) + "/textures/" + str(self._lat) + "-" + str(ln) + "_" + str(self._lng) + "-" + str(lt) + "_OG16.jpg", format='JPEG', subsampling=0, quality=100)

                # Adjust
                a_lng = a_lng + (mstr_zl_16 * 4)
                cur_lng = cur_lng + 4
                mstr_msg("tilegen", "Adjusted coordinate values")

            # Adjust
            a_lng = self._lat + (mstr_zl_16 * 2)
            a_lat = a_lat + (self._vstep * 4)
            cur_lat = cur_lat + 4
            cur_lng = self._lng
            mstr_msg("tilegen", "Adjusted coordinate values for next tile loop")

        mstr_msg("tilegen", "Tile generation... completed (wow.jpg)")


        # BUT! This is not the end. Yet.

        # Make sure we keep tiles around airports.
        airports = self._tiledb.get_tiles_with_airports()
        mstr_msg("tilegen", "Filtering ZL18 tiles for airports")

        # The ZL 18 tiles to keep in the end
        tiles = []
        mstr_msg("tilegen", "Finding ZL18 tiles to keep")
        for a in airports:
            tiles.append(findAirportTiles(int(a[1]), int(a[2])))
        mstr_msg("tilegen", "Determined ZL18 tiles")

        # Create a final array to make life easier
        mstr_msg("tilegen", "Generating arrays for tiles to keep")
        keeping = []
        for t in tiles:
            for i in t:
                keeping.append(i)

        # Perform the cleanup
        mstr_msg("tilegen", "Cleaning up non-needed tiles")
        for y in range(1, self._maxlat):
            for x in range(1, self._maxlng):
                fn = str(y) + "_" + str(x) + ".jpg"
                found = False
                for k in keeping:
                    kfn = str(k[0]) + "_" + str(k[1]) + ".jpg"
                    if fn == kfn:
                        found = True
                        break
                if found == False:
                    os.remove(mstr_datafolder + "/Tiles/" + str(self._lat) + "_" + str(self._lng) + "/textures/" + fn)
        mstr_msg("tilegen", "Cleanup completed")

        mstr_msg("tilegen", "Work complete.")



'''
    Did we fly to the moon too soon?
    Did we squander the chance?
    In the rush of the race
    The reason we chase is lost in romance
    And still we try
    To justify the waste
    For a taste of man's greatest adventure

    I blame you for the moonlit sky
    And the dream that died
    With the eagles' flights
    I blame you for the moonlit nights
    When I wonder why
    Are the seas still dry
    Don't blame this sleeping satellite
'''