# Copyright 2026 Purism, SPC
#
# 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

import sys
import gi
import logging

gi.require_version('Adw', '1')
gi.require_version('Gtk', '4.0')
gi.require_version("NM", "1.0")
gi.require_version("PackageKitGlib", "1.0")
gi.require_version("UPowerGlib", "1.0")

from gi.repository import Gtk, Adw

from .cards import WelcomeCard

class MemoryLoggingHandler(logging.Handler):
  def __init__(self):
    super().__init__()
    self.messages = []

  def emit(self, record):
    message = self.format(record)
    self.messages.append(message)
    logging.lastResort.emit(record)

class MainWindow(Adw.ApplicationWindow):

  closing = False

  def _on_close_request(self, window):
    return not self.leaflet.get_can_navigate_back() and not self.closing

  def _on_can_navigate_back(self, leaflet, prop):
    self.header.set_show_start_title_buttons(leaflet.get_can_navigate_back())
    self.header.set_show_end_title_buttons(leaflet.get_can_navigate_back())

  def quit(self):
    self.closing = True
    self.close()

  def restart(self):
    card = WelcomeCard()
    card.add_to(self.leaflet)

    while child := self.leaflet.get_adjacent_child(Adw.NavigationDirection.BACK):
      self.leaflet.remove(child)
      child.destroy()

    card.forward()

  def __init__(self, **kwargs):
    super().__init__(title="PureOS Upgrade", **kwargs)

    self.view = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

    self.leaflet = Adw.Leaflet(can_unfold=False)
    self.leaflet.connect("notify::visible-child", lambda leaflet, _: leaflet.get_visible_child().activate())
    self.leaflet.connect("notify::visible-child", lambda leaflet, _: leaflet.set_can_navigate_back(leaflet.get_visible_child().can_navigate_back()))
    self.leaflet.connect("notify::can-navigate-back", self._on_can_navigate_back)
    self.set_content(self.view)

    self.header = Adw.HeaderBar()

    back = Gtk.Button(icon_name="go-previous-symbolic", tooltip_text="Back")
    back.connect("clicked", lambda x: self.leaflet.navigate(Adw.NavigationDirection.BACK))
    self.leaflet.connect("notify::visible-child", lambda leaflet, _: back.set_visible(leaflet.get_can_navigate_back() and leaflet.get_adjacent_child(Adw.NavigationDirection.BACK)))
    self.header.pack_start(back)

    forward = Gtk.Button(label="Continue")
    forward.connect("clicked", lambda x: self.leaflet.get_visible_child().forward())
    self.leaflet.connect("notify::visible-child", lambda leaflet, _: forward.set_visible(leaflet.get_visible_child().wants_forward_button()))
    forward.add_css_class("suggested-action")
    self.header.pack_end(forward)

    restart = Gtk.Button(icon_name="view-refresh-symbolic", tooltip_text="Check again")
    restart.connect("clicked", lambda x: self.restart())
    self.leaflet.connect("notify::visible-child", lambda leaflet, _: restart.set_visible(leaflet.get_visible_child().wants_restart_button()))
    self.header.pack_end(restart)

    self.view.append(self.header)
    self.view.append(self.leaflet)

    self.set_default_size(800, 600)

    WelcomeCard().add_to(self.leaflet)

    self.connect("close-request", self._on_close_request)

class Application(Adw.Application):
  repos_changed = False

  def __init__(self, **kwargs):
    super().__init__(application_id="net.pureos.Upgrade", resource_base_path="/net/pureos/Upgrade", **kwargs)
    self.logHandler = MemoryLoggingHandler()
    logging.getLogger().addHandler(self.logHandler)

  def do_activate(self):
    win = self.props.active_window
    if not win:
        win = MainWindow(application=self)
    win.present()

  def set_repos_changed(self, changed):
    self.repos_changed = True

def main(version):
  return Application().run(sys.argv)

