#!/usr/bin/python3
import sys, os, locale, signal
import gi, subprocess, time, threading
from locale import gettext as _
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib, Pango
os.chdir(os.environ.get('SAVE_PWD', '/'))
if os.path.exists('updaterlib.py'):
  from updaterlib import *
else:
  from update_applet.updaterlib import *

import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)

INSTALL = True
SHOW_LOG = False
PULSE = False
DOMAIN = 'rosa-update-system'
LOCALE_DIR = '/usr/share/locale'
locale.bindtextdomain(DOMAIN, LOCALE_DIR)
locale.textdomain(DOMAIN)

UI = '/usr/share/update_applet/update_applet.ui'
install_cmd='kroko-cli autoinstall'
remove_cmd='dnf remove -y nvidia'
iconpath='/usr/share/update_applet'

#################### remove it
# install_cmd='dnf install -y nvidia550'
# remove_cmd='dnf remove -y nvidia550'
##############################

if os.path.exists('update_applet'):
  UI = './update_applet.glade'
  iconpath = os.path.abspath('./')

ICON = os.path.join(iconpath, 'update_applet_ok.svg')
green = os.path.join(iconpath,  'update_applet_ok.svg')
yellow = os.path.join(iconpath, 'update_applet_warning.svg')
red = os.path.join(iconpath, 'update_applet_error.svg')

def install():
    lines = 100
    app.update_button.hide()
    app.pwf_button.hide()
    app.progress.set_fraction(0.0)
    app.progress.show()
    if not runit(app, 'timeout 10m ' + install_cmd, _('Install NVIDIA driver')):
      echo(app, 'ERROR!!!', 'ERROR: ' + install_cmd)
      app.update_button.show()
      start_pulse(app, False)
      notify_send(_('Installation of NVIDIA driver failed'),
                  _('Try later, or use system package manager'), 'error', None, None)
      return False
    echo(app, '', _('Complete'))
    start_pulse(app, False)
    app.progress.set_fraction(1.0)
    if dialog(first=_('NVIDIA driver has been successfully installed') ,
              second=_('The system needs to be rebooted'),
              btn=[_("Reboot"), 1, _("Cancel"), 0 ] ):
      if not soft_reboot():
        time.sleep(2)
        hurd_reboot()
    exit()

def soft_reboot():
    try:
        subprocess.run(["reboot"], check=True)
        return True
    except (subprocess.CalledProcessError, PermissionError, FileNotFoundError):
        return False

def hard_reboot():
    try:
        subprocess.run(["sync"], check=True)
        subprocess.run(["reboot", "-f"], check=True)
    except Exception as e:
        print(f"Ошибка жесткой перезагрузки: {e}")

def remove():
    lines = 100
    app.update_button.hide()
    app.pwf_button.hide()
    app.progress.set_fraction(0.0)
    app.progress.show()
    if not runit(app, 'timeout 10m ' + remove_cmd, _('Remove NVIDIA driver')):
      echo(app, 'ERROR!!!', 'ERROR: ' + remove_cmd)
      app.update_button.show()
      notify_send(_('Dnf process of removing NVIDIA driver - failed'), \
                  _('Try later, or use system package manager'), 'error', None, None)
      start_pulse(app, False)
      return False
    echo(app, '', _('Complete'))
    start_pulse(app, False)
    app.progress.set_fraction(0)

    if dialog(first=_('NVIDIA driver has been successfully removed') ,
              second=_('The system needs to be rebooted'),
              btn=[_("Reboot"), 1, _("Cancel"), 0 ] ):
      if not soft_reboot():
        time.sleep(2)
        hurd_reboot()
    clear()
    return False

def clear():
    global INSTALL
    app.textbuffer.set_text('\n')
    app.statusbar.push(app.context_id, '')
    app.progress.set_pulse_step(0.2)
    app.text_window.hide()
    app.exit_button.set_label(_('Exit'))
    app.pwf_button.hide()
    app.update_button.show()
    start_pulse(app, False)
    app.log_chkbx.set_label(_('Show Log'))

    if SHOW_LOG:
        app.log_chkbx.set_active(True)
        app.text_window.show()
    else:
        app.log_chkbx.set_active(False)
        app.text_window.hide()

    if is_nvidia():
      INSTALL = False
      app.update_button.set_label(_('Start removing NVIDIA'))
      app.window.set_title(_('Remove NVIDIA driver'))
    else:
      INSTALL = True
      app.update_button.set_label(_('Star installing NVIDIA'))
      app.window.set_title(_('Install NVIDIA driver'))
    app.progress.set_text(_('Install') if INSTALL else _('Remove'))


def exit(*args):
  try:
    os.remove(lockfile)
  except:
    pass
  Gtk.main_quit()

class WinHandler:
    def on_CHECK_HALT_activate(self, button):
        pass

    def on_show_log_toggled(self, button):
      global SHOW_LOG
      if app.log_chkbx.get_active():
          app.text_window.show()
          SHOW_LOG = True
      else:
          w, h = app.window.get_size()
          app.text_window.hide()
          app.window.resize(w, app.window.get_preferred_height()[1])
          SHOW_LOG = False

    def onSUBMIT(self, button):
        global INSTALL
        clear()
        bat = powercheck()
        if bat < 20:
            if not  dialog(first=_("Attention!\nThe battery charge status is low: ") + f'{bat}%',
                           second=_("Continue?"), btn=[Gtk.STOCK_YES, 1, Gtk.STOCK_NO, 0 ] ):
                return
        start_pulse(app, True)
        if INSTALL:
          GLib.idle_add(install)
        else:
          GLib.idle_add(remove)

    def onEXIT(self, button):
        exit()

class Applet:
  def __init__(self):
    self.force = False
    # window
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    builder = Gtk.Builder()
    self.builder = builder
    builder.set_translation_domain(DOMAIN)
    builder.add_from_file(UI)

    textaria = builder.get_object('TEXTAREA')
    textaria.override_font(Pango.FontDescription('Monospace 10'))
    self.textbuffer = textaria.get_buffer()

    self.progress = builder.get_object('PROGRESS')
    self.statusbar = builder.get_object('STATUS')
    self.text_window = builder.get_object('SCROLL')
    self.context_id = self.statusbar.get_context_id('updater')

    self.log_chkbx = builder.get_object('show_log')
    self.update_button = builder.get_object('SUBMIT')
    self.exit_button = builder.get_object('EXIT')
    self.pwf_button = builder.get_object('CHECK_HALT')
    builder.connect_signals(WinHandler())
    self.scroll = builder.get_object('SCROLL')

    self.window = builder.get_object('window_main')
    self.window.set_icon_from_file(ICON)
    self.window.connect("destroy", Gtk.main_quit)

  def run(self):
    self.window.show_all()
    clear()
    if self.force:
      handler = WinHandler()
      handler.onSUBMIT(None)
    Gtk.main()

if __name__ == '__main__':

  # самоубиться если лайв ОС
  if os.path.exists('/dev/mapper/live-base'):
    print('Live OS detected, quit!')
    quit()

  # самоубиться если другой экземпляр запущен
  os.makedirs(os.path.join('/run/user', str(os.getuid())), exist_ok=True)
  lockfile = os.path.join('/run/user', str(os.getuid()), 'kroko_gui')
  proc = is_allready_running(lockfile)
  if proc and 'kroko_gui' in proc:
      print('ERROR')
      dialog(first=_('ERROR'), second=_('Another util was found!'), mtype='error', btn=[_("I Understand"), 0] )
      quit()

  # устанавливаем новый lock файл.
  with open(lockfile, 'w') as f:
      print(str(os.getpid()), file=f)
  force = False
  if len(sys.argv) == 2 and sys.argv[1] == '--force':
    force = True

  # запуск приложения
  app = Applet()
  app.force = force
  notify_init(_('kroko_gui'))
  app.run()


