# maps_page.py
#
# Copyright 2024 Christopher Talbot
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later

from gi.repository import Adw
from gi.repository import Gtk
from gi.repository import Shumate

import datetime
import socket
import os
import gtk_meshtastic_client.maps_marker as maps_marker
import gtk_meshtastic_client.utils as utils
import atexit

@Gtk.Template(resource_path='/org/kop316/meshtastic/ui/maps_page.ui')
class MapsPageBin(Adw.Bin):
    __gtype_name__ = 'MapsPageBin'

    simple_map = Gtk.Template.Child()
    first_load = False
    longitude_last_seen = 0
    latitude_last_seen = 0

    own_node_latitude = 0
    own_node_longitude = 0

    def define_longitude_last_seen(self, longitude):
            self.longitude_last_seen = longitude

    def define_latitude_last_seen(self, latitude):
        self.latitude_last_seen = latitude

    def close_gps_socket(self):
        socket_path = os.environ['XDG_RUNTIME_DIR'] + "/meshtastic-gnss.sock"
        if not hasattr(self, 'server'):
            self.logger.debug("GPS Socket not active")
            try:
                os.remove(socket_path)
            except FileNotFoundError:
                pass
            return

        self.server.close()
        try:
            os.remove(socket_path)
        except FileNotFoundError:
            pass

    def create_gps_socket(self):
        if hasattr(self, 'server'):
            self.logger.debug("GPS Socket already active")
            return

        socket_path = os.environ['XDG_RUNTIME_DIR'] + "/meshtastic-gnss.sock"

        try:
            os.remove(socket_path)
        except FileNotFoundError:
            pass

        self.server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        self.server.bind(socket_path)
        self.server.listen()
        self.server.setblocking(False)

    def load_own_node_lat_long(self, lat, lng, alt):
        app = Gtk.Application.get_default()

        if app.app_settings.get_create_gps_socket():
            self.create_gps_socket()

            msgsp = utils.gga_sentence_builder(lat, lng, alt)

            try:
                conn, addr = self.server.accept()
                conn.sendmsg([msgsp.encode("utf-8")])
            except BlockingIOError:
                pass
            except BrokenPipeError:
                pass

        self.own_node_latitude = lat
        self.own_node_longitude = lng

    def reset_map(self):
        self.marker_layer.remove_all()
        self.longitude_last_seen = 0
        self.latitude_last_seen = 0
        self.own_node_latitude = 0
        self.own_node_longitude = 0
        self.first_load = False

    def goto_map(self, lat, lng, zoom):
        goto_map = self.simple_map.get_map()
        goto_map.go_to_full(lat, lng, zoom)

    def goto_map_first_load(self, lat, lng):
        if not self.first_load:
            self.first_load = True
            self.goto_map(lat, lng, 12)

    def goto_map_last_seen_first_load(self):
        """
        Don't bother trying to update lat and long if there's no entries
        """
        if not self.first_load and self.latitude_last_seen != 0 and self.longitude_last_seen != 0:
            self.first_load = True
            self.goto_map(self.latitude_last_seen, self.longitude_last_seen, 10)

    def add_marker_to_map(self, marker):
        self.marker_layer.add_marker (marker)

    @Gtk.Template.Callback()
    def _maps_page_zoom_button_clicked_cb(self, button):
        if not self.first_load:
            self.logger.debug("Not loaded")
            return
        if self.own_node_latitude != 0 and self.own_node_longitude != 0:
            self.goto_map(self.own_node_latitude, self.own_node_longitude, 12)
            return
        else:
            self.goto_map(self.latitude_last_seen, self.longitude_last_seen, 10)
            return

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        app = Gtk.Application.get_default()
        self.logger = app.logger

        self.registry = Shumate.MapSourceRegistry.new_with_defaults()
        map_source = self.registry.get_by_id(Shumate.MAP_SOURCE_OSM_MAPNIK)
        self.simple_map.set_map_source(map_source)

        viewport = self.simple_map.get_viewport()

        self.marker_layer = Shumate.MarkerLayer.new(viewport)
        self.simple_map.add_overlay_layer(self.marker_layer)

        if app.app_settings.get_create_gps_socket():
            self.create_gps_socket()

        atexit.register(self.cleanup)

    def cleanup(self):
        self.close_gps_socket()
