# -------------------------------------------------------------------
# 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
# -------------------------------------------------------------------
# tiledb.py
# Manages information concerning the information for a particular
# tile, particularly its consisting smaller subtiles. Used for
# consistent layer generation.
# -------------------------------------------------------------------

import sqlite3
from defines import *
from functions import *
from log import *

class mstr_tiledb:
    def __init__(self, lat, lng):
        # Note coords
        self._latitude  = lat
        self._longitude = lng

        # The db file will be created, should it not exist
        self._conn = sqlite3.connect(mstr_datafolder + "Tiles\\" + str(self._latitude) + "_" + str(self._longitude) + "\\data.db")
        self._crs = self._conn.cursor()
        #mstr_msg("tiledb", "Database object initiated")


    # Opens a database file - used by maskgen
    def openDB(self, dbfile):
        self._conn = sqlite3.connect(dbfile + ".db")
        self._crs = self._conn.cursor()


    # Creates tables for this particular degree of lat/lng
    def create_tables(self):
        self._conn.execute("CREATE TABLE IF NOT EXISTS tiledata (tile_v INTEGER, tile_h INTEGER, tag TEXT, value TEXT, source INTEGER, adjacent TEXT);")
        self._conn.execute("CREATE TABLE IF NOT EXISTS airports (icao TEXT, tile_v INTEGER, tile_h INTEGER, latitude REAL, longitude REAL);")
        self._conn.execute("CREATE TABLE IF NOT EXISTS completion (tile_v INTEGER, tile_h INTEGER, tag TEXT, value TEXT, source INTEGER, adjacent TEXT);")
        #mstr_msg("tiledb", "Tables created")

    
    # Insert data into their segments
    def insert_info(self, tv, th, tag, value, src, adj):
        self._conn.execute("INSERT INTO tiledata VALUES ( "+ str(tv) +", "+ str(th)+", '"+ tag +"', '"+ value +"', '"+ str(src) +"', '"+adj+"' );")
    
    # Insert data into the completion data
    def insert_completion_info(self, tv, th, tag, value, src, adj):
        self._conn.execute("INSERT INTO completion VALUES ( "+ str(tv) +", "+ str(th)+", '"+ tag +"', '"+ value +"', '"+ str(src) +"', '"+adj+"' );")

    # Insert an airport with ICAO code
    def insert_icao(self, icao, tv, th, lat, lng):
        self._conn.execute("INSERT INTO airports VALUES ('"+icao+"', "+str(tv)+", "+str(th)+", "+str(lat)+", "+str(lng)+");")


    # Commit a query or a number of queries
    def commit_query(self):
        self._conn.commit()


    # Retrieve the adjacency string for normal tile generation
    def get_adjacency_for_source(self, v, h, tag, value):
        r = self._crs.execute("SELECT * FROM tiledata where tile_v="+str(v)+" and tile_h="+str(h)+" and tag='"+tag+"' and value='"+value+"';")
        rws = r.fetchall()
        return rws
    
    # Retrieve the adjacency info for completion of a tile
    def get_adjacency_for_completion(self, v, h):
        r = self._crs.execute("SELECT * FROM completion where tile_v="+str(v)+" and tile_h="+str(h)+";")
        rws = r.fetchall()
        return rws
    
    # These calls are a bit more complex. We also need to know adjacency info when we are directly
    # next to another latitude or longitude. We want seamless generation in those situations too.
    def get_adjacency_for_source_in_lat_lng(self, lat, lng, v, h, tag, value):
        # The rows to return
        rws = []

        # For this we need to tap into the database of the tile, should there be one.
        dbn = mstr_datafolder + "Tiles\\" + str(lat) + "_" + str(lng) + "\\data.db"
        if os.path.isfile(dbn):
            tileconn = sqlite3.connect(dbn)
            tilecrsr = tileconn.cursor()
            r = tilecrsr.execute("SELECT * from tiledata WHERE tile_v="+str(v)+" AND tile_h="+str(h)+" AND tag='"+tag+"' AND value='"+value+"';")
            rws = r.fetchall()
            tileconn.close()

        return rws
    
    # These calls are a bit more complex. We also need to know adjacency info when we are directly
    # next to another latitude or longitude. We want seamless generation in those situations too.
    def get_adjacency_for_completion_in_lat_lng(self, lat, lng, v, h):
        # The rows to return
        rws = []

        # For this we need to tap into the database of the tile, should there be one.
        dbn = mstr_datafolder + "Tiles\\" + str(lat) + "_" + str(lng) + "\\data.db"
        if os.path.isfile(dbn):
            tileconn = sqlite3.connect(dbn)
            tilecrsr = tileconn.cursor()
            r = tilecrsr.execute("SELECT * from completion WHERE tile_v="+str(v)+" AND tile_h="+str(h)+";")
            rws = r.fetchall()
            tileconn.close()

        return rws
    
    # Acquire the highest latitude and longitude tile number of a neighbouring tile
    def get_highest_latlong_from_tile(self, lat, lng):
        latlng = [-1, -1]
        # For this we need to tap into the database of the tile, should there be one.
        dbn = mstr_datafolder + "Tiles\\" + str(lat) + "_" + str(lng) + "\\data.db"
        if os.path.isfile(dbn):
            tileconn = sqlite3.connect(dbn)
            tilecrsr = tileconn.cursor()
            lt = tilecrsr.execute("SELECT * FROM tiledata ORDER BY tile_v DESC")
            rws = lt.fetchall()
            lat = rws[0][0]
            ln = tilecrsr.execute("SELECT * FROM tiledata ORDER BY tile_h DESC")
            rws = ln.fetchall()
            lng = rws[0][1]
            latlng[0] = lat
            latlng[1] = lng
            tileconn.close()
        
        return latlng

    # Get all tiles with detected airports (ICAO codes)
    def get_tiles_with_airports(self):
        r = self._crs.execute("SELECT * FROM airports")
        rws = r.fetchall
        return rws


    # Perform a custom query and retrieve results
    def perform_query(self, qry):
        r = self._crs.execute(qry)
        rws = r.fetchall()
        return rws


    # Close DB
    def close_db(self):
        mstr_msg("tiledb", "Closing database connection")
        self._conn.close()