# message_parser.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 GLib
import gettext
import meshtastic.serial_interface
import meshtastic.mesh_interface
from pubsub import pub
import json
import time
import os

import gtk_meshtastic_client.utils as utils

def process_packet_cb(packet) -> bool:
    app = Gtk.Application.get_default()
    win = Gtk.Application.get_active_window(app)

    app.logger.debug("New message")
    if not hasattr(win.connection_page_bin, 'interface'):
        app.logger.warning("Warning: Received packet but you are disconnected!")
        return GLib.SOURCE_REMOVE

    if packet['decoded'].get('portnum') == 'TELEMETRY_APP':
        win.nearby_nodes_page_bin.packet_node_update(packet, win.connection_page_bin.interface)
        return GLib.SOURCE_REMOVE
    elif packet['decoded'].get('portnum') == 'NODEINFO_APP':
        win.nearby_nodes_page_bin.packet_node_update(packet, win.connection_page_bin.interface)
        return GLib.SOURCE_REMOVE
    elif packet['decoded'].get('portnum') == 'POSITION_APP':
        win.nearby_nodes_page_bin.packet_node_update(packet, win.connection_page_bin.interface)
        return GLib.SOURCE_REMOVE

    elif packet['decoded'].get('portnum') == 'TEXT_MESSAGE_APP':
        win.channels_page_bin.new_text_message(packet, win.connection_page_bin.interface)
        return GLib.SOURCE_REMOVE

    elif packet['decoded'].get('portnum') == 'ROUTING_APP':
        if 'priority' in packet:
            if packet['priority'] == "ACK":
                 win.channels_page_bin.process_ack_message(packet, win.connection_page_bin.interface)
                 return GLib.SOURCE_REMOVE
        if packet['to'] == win.connection_page_bin.interface.myInfo.my_node_num:
            win.channels_page_bin.process_routing_app_message(packet, win.connection_page_bin.interface)
            return GLib.SOURCE_REMOVE

    return GLib.SOURCE_REMOVE

class MessageParser():

    def onReceive(self, packet, interface):
        app = Gtk.Application.get_default()
        win = Gtk.Application.get_active_window(app)

        if app.app_settings.get_log_packets():
            json_packet = json.dumps(packet, indent=4, default=lambda s: " ".join(str(s).split()))
            if os.path.exists(utils.messages_file_path):
                with open(utils.messages_file_path, 'r+') as json_file:
                    content = json_file.read().strip()
                    if content:
                        if content.endswith(']'):
                            content = content[:-1].rstrip() + ',\n'
                        else:
                            content = '['
                        json_file.seek(0)
                        json_file.write(content + json_packet + '\n]')
                    else:
                        json_file.seek(0)
                        json_file.write('[' + json_packet + '\n]')
                    json_file.truncate()
            else:
                with open(utils.messages_file_path, 'w') as json_file:
                    json_file.write('[\n' + json_packet + '\n]')

        if app.app_settings.get_print_packets():
            print(f"{packet} \n\n")

        if 'decoded' in packet:
            app = Gtk.Application.get_default()
            win = Gtk.Application.get_active_window(app)

            """
            For some reason if this is all synchronous, GTK does a lot of weird segfaults
            This is also longer than the connection page timeout to ensure that any packets
            that come right on connection are processed after the nearby nodes page
            is set up
            """
            GLib.timeout_add(100, process_packet_cb, packet)
            return

    def __init__(self):
        app = Gtk.Application.get_default()
        self.logger = app.logger

        # The python library will automatically process any messages stored, so there
        # is no need to manually scan for messages on connection
        pub.subscribe(self.onReceive, 'meshtastic.receive')
