#!/usr/bin/python3
import sys, os, locale, requests, threading, time
from locale import gettext as _
from datetime import datetime
import gi, subprocess, time, pickle, signal, shutil
gi.require_version('Gtk', '3.0')
gi.require_version('AyatanaAppIndicator3', '0.1')
from gi.repository import Gtk, GLib, Pango
from gi.repository import AyatanaAppIndicator3 as appindicator
if os.path.exists('updaterlib.py'):
  from updaterlib import *
else:
  from update_applet.updaterlib import *

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

# from updaterlib
iconpath = COMMON.getpath()
autostartdir = COMMON.autostartdir()
token_file = COMMON.token_file
UI = os.path.join(COMMON.getpath(), COMMON.UI)

cfgdir = os.environ['HOME'] + '/.config/update_applet'
desktopfile = '/usr/share/applications/update_applet.desktop'

os_data = sysinfo()
get_key_url = 'https://mirror.rosa.ru/r/rosa-chrome-buy?version=' + os_data['platform']

update_cmd='pkexec barium update -uv'
check_cmd='barium update -cv'

APP = 'barium_applet'
locale.bindtextdomain(APP, COMMON.LOCALE_DIR)
locale.textdomain(APP)

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

h = {}
h['ROOTFS'] = _('ROOTFS')
h['DISK_USAGE'] = _('DISK USAGE')
h['MEM'] = _('MEM')
h['LAST_SAVE'] = _('LAST SAVE')
h['HOME_DIR_SIZE'] = _('HOME DIR SIZE')
h['HOME_MODULE_SIZE'] = _('HOME MODULE SIZE')
h['SAVE_TIMEOUT'] = _('SAVE TIMEOUT')
used_ = _('used')
available_ = _('available')
min_ = _('min')
Mb = _('Mb')
disabled_ = _('disabled')
maxlen = len(max( h.values() , key=len)) + 2
for key, val in h.items():
  quant = (maxlen - len(val) + 2) // 5
  tabs = str('_' * quant).replace('_', '\t')
  h[key] = val + ': ' + tabs

#default values
config = {}
config['times'] = (1, 5, 10, 30, disabled_ ) # min
config['synctimeout'] = 30 # min (one of times)
config['upd_times'] = (1, 3, 5, 10, 30) # sec
config['timeout'] = 5 # sec (one of upd_times)
config['show_log'] = False

new_interval = False
INPROGRESS = False

@debug_decorator
def update():
    global INPROGRESS
    INPROGRESS = True
    app.update_button.hide()
    app.pwf_button.hide()
    app.progress.set_fraction(0.0)
    start_pulse(app, True)
    app.progress.show()
    if not runit(app, 'timeout 60m ' + update_cmd, _('Update ')):
      echo(app, _('ERROR!!!'), _('ERROR: ') + update_cmd)
      app.update_button.show()
      notify_send(_('Update process - failed'), \
                  _('Please, try later'), 'error', None, None)
      start_pulse(app, False)
      app.progress.set_fraction(0.0)
      app.progress.hide()
      INPROGRESS = False
      return False
    echo(app, '', _('Complete'))
    start_pulse(app, False)
    app.progress.set_fraction(1.0)
    if dialog(first=_("Update complete!"), second=_('A system reboot is required to complete the update process.'), btn=[_('Reboot now'), 1, _('Later'), 0 ] ):
        reboot_timer(30)
    app.ind_app.set_status (appindicator.IndicatorStatus.ACTIVE)
    app.window.hide()
    INPROGRESS = False

@debug_decorator
def get_updates():
    global INPROGRESS
    clear()
    app.ind_app.set_status (appindicator.IndicatorStatus.PASSIVE)
    app.progress.set_fraction(0.0)
    start_pulse(app, True)
    INPROGRESS = True
    if not runit(app, 'timeout 5m ' + check_cmd, _('Check updates ')):
      echo(app, _('Updates not found!\nCheck cmdline: ')  + check_cmd , _('Updates not found!'))
      start_pulse(app, False)
      app.progress.hide()
      INPROGRESS = False
      return False
    echo(app, '', _('Check complete: ') + _('Updates found'))
    start_pulse(app, False)
    app.progress.set_fraction(0)
    app.update_button.show()
    app.pwf_button.show()
    INPROGRESS = False

@debug_decorator
def clear():
    global INSTALL
    app.textbuffer.set_text('\n')
    app.statusbar.push(app.context_id, '')
    start_pulse(app, False)
    app.progress.hide()
    app.text_window.hide()
    app.exit_button.set_label(_('Hide'))
    app.pwf_button.hide()
    app.update_button.hide()
    start_pulse(app, False)
    app.log_chkbx.set_label(_('Details...'))

    if config['show_log']:
        app.log_chkbx.set_active(True)
        app.text_window.show()
    else:
        app.log_chkbx.set_active(False)
        app.text_window.hide()
    if os_data["branding"] and os_data["release"]:
        app.release_label.set_markup(f'<span style="italic" weight="light" size="small">{os_data["branding"]} {os_data["release"]}</span>')
        app.release_label.show()

def pickle_write():
  with open(cfgdir + '/dump', 'wb') as f:
   pickle.dump(config, f)

@debug_decorator
def stoptimers():
    global timer_id
    if 'timer_id' in globals():
      GLib.Source.remove(timer_id)
    timer_id = False
    dprint('stop timers')


class WinHandler:
  def on_CHECK_HALT_activate(self, *args):
      pass
  def on_release_eventbox_enter_notify_event(self, *args):
      pass
  def on_exit_button_dialog_clicked(self, *args):
      pass
  def on_release_eventbox_leave_notify_event(self, *args):
      pass
  def on_release_eventbox_button_press_event(self, *args):
      pass

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

  @debug_decorator
  def onSUBMIT(self, button):
      global INSTALL
      global INPROGRESS
      if INPROGRESS:
        return False
      clear()
      bat = powercheck()
      if bat < 40:
          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)
      GLib.idle_add(update)

  def onEXIT(self, button):
      global timer_id
      app.ind_app.set_status (appindicator.IndicatorStatus.ACTIVE)
      app.window.hide()


class IndHandler():
  def exit(*args):
    Gtk.main_quit()

  def check_updates(*args):
    global INPROGRESS
    stoptimers()
    app.window.show_all()
    app.update_button.hide()
    app.pwf_button.hide()
    if not INPROGRESS:
        get_updates()

  def luks(*args):
    subprocess.call( [ 'pkexec', 'barium', 'luks-manager'] )

  def tobackup(*args):
    script = '''#!/bin/bash
  DISTRDEV=$(grep -m1 " %s/layer-base/0 " /proc/self/mountinfo | awk '{ print $10 }')
  DISTRMPOINT=$(findmnt -lnf $DISTRDEV -o TARGET)
  DISTRPATH=$DISTRMPOINT$(grep -m1 " %s/layer-base/0 " /proc/self/mountinfo | awk '{ print $4 }')
  [ "${DISTRPATH##*.}" != bak ] && exit 1
  mount -o remount,rw $DISTRMPOINT
  mv ${DISTRPATH/.bak} ${DISTRPATH/.bak}.upd
  mv ${DISTRPATH} ${DISTRPATH/.bak} || exit 2
  exit 0
  ''' % ( initvars['SYSMNT'], initvars['SYSMNT'])
    with open('/tmp/switch_to_backup.sh', 'w') as f:
      print( script, file=f )
    os.chmod('/tmp/switch_to_backup.sh', 0o755)
    ret = subprocess.call( [ 'pkexec', '/tmp/switch_to_backup.sh' ] )
    app.menu_tobackup.destroy()
    if ret == 0:
      notify_send(_('The system has been successfully switched to backup state'), _('Please reboot'), 'ok', None, None)
      return True
    elif ret == 1:
      notify_send(_('Error:'), _('Backup not found'), 'error', None, None)
    elif ret == 2:
      notify_send(_('Error:'), _('Can not switch to backup'), 'error', None, None)
    else:
      notify_send(_('Error:'), _('Unknown'), 'error', None, None)
    return False

  def toggle_saves(*args):
    if os.path.exists('/run/initramfs/shutdown'):
      ret = subprocess.call( [ 'pkexec', 'mv', '/run/initramfs/shutdown' , '/run/initramfs/shutdown.bak' ])
      if not ret:
        app.menu_toggle_saves.set_label(_('Enable saves'))
    else:
      ret = subprocess.call( [ 'pkexec', 'mv', '/run/initramfs/shutdown.bak' , '/run/initramfs/shutdown' ])
      if not ret:
        app.menu_toggle_saves.set_label(_('Disable saves'))

  def rmbak(*args):
    subprocess.call([
        'pkexec', 'sh', '-c',
        f'rm -f {initvars["SYSMNT"]}/layer-base/1/saves/*.xzm.bak'
    ])

  def synchome(*args):
    ret = progress_run( lambda x=['pkexec', 'synchome']: subprocess.call(x),
                        _('Synchome'), _('saving /home directory') )
    if ret:
      notify_send(_('Error:'), _('Command synchome exited with error: ') + str(ret), 'error', None, None)
    with open( '/tmp/synchome', 'w' ) as f:
      f.write(str(int(time.time())))

  def set_token(*args):
    if not set_token():
      return
    if not check_request(os_data):
      notify_send(_('Attention!'), _('Wrong or obsolete key, or error in the server side'), 'warning', False )
      fn_set_token()

#генератор функций для каждого значение в кортеже times
fn_save = {}
def f1(time_):
  global config
  if type(time_) == int:
    app.handler.synchome()
  if type(config['synctimeout']) == int:
    app.submenu_save_item[config['synctimeout']].set_label( str(config['synctimeout']) + ' ' + _('min') )
  else:
    app.submenu_save_item[config['synctimeout']].set_label( str(config['synctimeout']) )
  config['synctimeout'] = time_
  pickle_write()
for i in config['times']:
  fn_save[i] = lambda x, y, i=i: f1(i)

#генератор функций для каждого значение в кортеже upd_times
fn_icon_update = {}
def f2(time_):
  global config
  global timer_id
  global new_interval
  app.submenu_icon_item[config['timeout']].set_label(str(config['timeout']) + ' ' + _("sec") )
  config['timeout'] = time_
  new_interval = True
  app.submenu_icon_item[config['timeout']].set_label(str(config['timeout']) + ' ' + _("sec") + _(" *") )
  new_interval = True
  pickle_write()
for i in config['upd_times']:
  fn_icon_update[i] = lambda x, y, i=i: f2(i)

@debug_decorator
def reboot_timer(time):
    if not poweroff('reboot'):
        pwf_id = GLib.timeout_add_seconds(time, os.execlp, 'reboot', 'reboot')
        if dialog(first=_("Time to reboot: ")+ str(pwf_time), second=_("Cancel?"), btn=[Gtk.STOCK_YES, 1, Gtk.STOCK_NO, 0 ] ):
            GLib.Source.remove(pwf_id)

@debug_decorator
def fn_getvalues(ind_app):
  global new_interval
  available = {}
  used = {}
  for name, path in ([ 'rootfs',  '/' ], [ 'disk', initvars['SYSMNT'] + '/layer-base/1' ]):
    with subprocess.Popen([ 'df', path, '-m', '/'], stdout=subprocess.PIPE) as fs:
      lines = fs.stdout.readlines()
      valueline = lines[1].decode('utf-8').split()
      available[name] = valueline[3]
      used[name] = valueline[4][0:-1]
  with subprocess.Popen(['free', '-m'], stdout=subprocess.PIPE) as free:
    lines = free.stdout.readlines()
    valueline = lines[1].decode('utf-8').split()
    available['free'] = valueline[6]
    used['free'] = float('{:.2f}'.format(int(valueline[2]) * 100 / int(valueline[1])))
  if os.path.exists('/tmp/synchome'):
    with open( '/tmp/synchome', 'r' ) as f:
      lastsave = str(f.readlines()[0])
      timestamp = int(time.time())
      delta = int((timestamp - int(lastsave)) / 60)
      if type(config['synctimeout']) == int  and delta >= config['synctimeout']:
        app.handler.synchome()
  else:
      delta = _('never')
  if ishomexzm:
    homesize = float('{:.2f}'.format(os.stat(initvars['SYSMNT'] + '/layer-base/1/saves/homes.xzm').st_size / 1024 / 1024))
  else:
    homesize = 0
  with subprocess.Popen([ 'du', '/home', '-sm'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) as home:
    homedirsize = str(home.stdout.readline().decode('utf-8').split()[0])
  if type(config['synctimeout']) == int:
    timeoutstr = str(config['synctimeout']) + ' ' + min_
  else:
    timeoutstr = config['synctimeout']
  title = f'''
{h['ROOTFS']}{available_}: {available['rootfs']}{Mb}, {used_}: {used['rootfs']}%
{h['DISK_USAGE']}{available_}: {available['disk']}{Mb}, {used_}: {used['disk']}%
{h['MEM']}{available_}: {available['free']}{Mb}, {used_}: {used['free']}%
{h['HOME_DIR_SIZE']}{homedirsize}{Mb}
'''
  if ishomexzm:
    title += f'''
{h['HOME_MODULE_SIZE']}{homesize}{Mb}'
{h['LAST_SAVE']}{delta} {min_}
{h['SAVE_TIMEOUT']}{timeoutstr}
'''
  ind_app.set_title(title)

  color = 'green'
  if ishomexzm:
    if int(homedirsize) / 1.5 >= int(available['disk']) or \
    int(homesize) >= 500:
      color = 'yellow'

  if not ischanges and int(used['rootfs']) >= 80:
    color = 'yellow'

  if int(used['free']) >= 80:
    color = 'yellow'

  if ishomexzm:
    if int(homedirsize) / 2 >= int(available['disk']) or \
    int(homesize) >= 1000:
      color = 'red'

  if istoxzm and not os.path.exists('/run/initramfs/shutdown'):
    color = 'red'

  if not ischanges and int(used['rootfs']) >= 95:
    color = 'red'

  if int(used['free']) >= 95:
    color = 'red'
  if color == 'red':
    if app.ind_app.get_icon != red:
      app.ind_app.set_icon_full(red, "red")
      app.menu_rmback.show()
  elif color == 'yellow':
    if app.ind_app.get_icon != yellow:
      app.ind_app.set_icon_full(yellow, "yellow")
      app.menu_rmback.show()
  elif color == 'green':
    if app.ind_app.get_icon != green:
      app.ind_app.set_icon_full(green, "green")
      app.menu_rmback.hide()
  if ishomexzm:
    if type(config['synctimeout']) == int:
      app.submenu_save_item[config['synctimeout']].set_label( str(config["synctimeout"]) + ' ' + _('min') + ' *' )
    else:
      app.submenu_save_item[config['synctimeout']].set_label(disabled_ + ' *')

  if new_interval:
    new_interval = False
    GLib.timeout_add(config['timeout'] * 1000, fn_getvalues, ind_app)
    dprint(f'set timeout: {config["timeout"]}')
    return False
  else:
    return True

@debug_decorator
def show_saves(app, times):
  for itime  in times:
    if type(itime) == int:
      app.submenu_save_item[itime] = Gtk.MenuItem( label=str(itime) + ' ' + _('min') )
    else:
      app.submenu_save_item[itime] = Gtk.MenuItem( label=str(itime))
    app.submenu_save_item[itime].connect("activate", fn_save[itime], '')
    app.submenu_save_item[itime].show()
    app.submenu_save.append(app.submenu_save_item[itime])

@debug_decorator
def show_icon_update(app, times):
  for itime  in times:
    app.submenu_icon_item[itime] = Gtk.MenuItem( label=str(itime) + ' ' + _('sec') )
    app.submenu_icon_item[itime].connect("activate", fn_icon_update[itime], '')
    app.submenu_icon_item[itime].show()
    app.submenu_icon_update.append(app.submenu_icon_item[itime])

def check_token():
  if not os.path.exists(token_file):
    return True
  elif os.stat(token_file).st_size != 0:
    return True
  else:
    return set_token()

@debug_decorator
def set_token(*args):
  global os_data
  stoptimers()
  token = get_token()
  if not token:
    return False
  ret = subprocess.Popen([ 'pkexec bash -c "echo ' + token + ' > ' + token_file + '"'], stdout=subprocess.PIPE, shell=True).wait()
  if ret != 0:
    dialog(first=_('Error'), second=_('Can not save token!'), mtype='error')
    return False
  try:
    with open(token_file, 'r') as f:
      os_data['token'] = f.read().strip()
  except:
      os_data['token'] = 'not set'
  return True

# вернет либо введенный в диалогово окошке ключ либо False
@debug_decorator
def get_token():
  token = dialog(first=_('Warning'), second=_('For access for Rosa repos please enter the key'), mtype='info',
                 entry=True, btn=[_("Confirm"), 1, _("I have no key"), 0 ], above=False)
  if not token:
    subprocess.Popen( ['nohup', 'xdg-open', get_key_url ],
                      start_new_session=True,
                      stdout=subprocess.DEVNULL,
                      stdin=subprocess.DEVNULL,
                      stderr=subprocess.DEVNULL )
    token = dialog(first=_('Warning'), second=_('For access for Rosa repos please enter the key'), mtype='info', entry=True,  btn=[_("Confirm"), 1, _("Remind later"), 0 ])
    if not token:
      return False
  token = str(token).strip()
  while not ( len(token) == 15 and token == token.lower() and token.isalnum() ):
    token = dialog(first=_('Wrong token format'), second=_('Please enter the key again'), mtype='info', entry=True, btn=[_("Confirm"), 1, _("Remind later"), 0 ])
    if not token:
      #os.execlp('xdg-open', 'xdg-open', get_key_url)
      return False
    token = str(token).strip()
  return token

@debug_decorator
def first_check():
  dprint('first check')
  first_counter = int(time.perf_counter())
  checknet = False
  waittime = 0
  while checknet == False and  waittime <= 60:
    dprint(f'Network check time: {waittime} sec')
    for addr in ('https://ya.ru', 'https://abf.io', 'https://google.com'):
      try:
        requests.get(addr).status_code
        checknet = True
        break
      except:
        time.sleep(1)
    waittime = int(time.perf_counter()) - first_counter
  GLib.idle_add(lambda text=_("Check repository permissions..."): app.ind_app.set_title(text))
  refresh()
  if os.path.exists(token_file) and not check_request(os_data):
    GLib.idle_add(lambda : (notify_send(_('Attention!'), _('Wrong or obsolete key, or error in the server side'), 'warning', None, None ), False)[1])
    GLib.idle_add(lambda: (set_token(), False)[1])
  GLib.idle_add(lambda text=_("Check updates..."): app.ind_app.set_title(text))

class Applet:
  def __init__(self):
    self.submenu_icon_item = {}
    self.submenu_save_item = {}
    self.handler = IndHandler()

     # update window
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    builder = Gtk.Builder()
    builder.set_translation_domain(APP)
    builder.add_from_file(UI)
    self.builder = builder

    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.release_label = builder.get_object('release_label')

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

    # indicator
    self.ind_app = appindicator.Indicator.new (
       "update-status-indicator",
       green,
       appindicator.IndicatorCategory.SYSTEM_SERVICES)
    self.ind_app.set_status (appindicator.IndicatorStatus.ACTIVE)
    self.ind_app.set_title(_("Barium applet") + ' ' + get_os_name())
    self.ind_app.set_status (appindicator.IndicatorStatus.ACTIVE)

    # create a menu
    menu = Gtk.Menu()

    if ishomexzm:
      menu_save_now = Gtk.MenuItem(label=_('Save home now'))
      menu_save_now.connect("activate", self.handler.synchome, '')
      menu_save_now.show()
      menu.append(menu_save_now)

      ######## autosave
      submenuItem = Gtk.MenuItem(label=_('Auto saving of /home'))
      self.submenu_save = Gtk.Menu()
      submenuItem.set_submenu(self.submenu_save)
      menu.append(submenuItem)
      submenuItem.show()
      show_saves(self, config['times'])

    ######## update applet
    submenuItem2 = Gtk.MenuItem(label=_('Applet update interval'))
    self.submenu_icon_update = Gtk.Menu()
    submenuItem2.set_submenu(self.submenu_icon_update)
    menu.append(submenuItem2)
    submenuItem2.show()
    show_icon_update(self, config['upd_times'])
    self.submenu_icon_item[config['timeout']].set_label(str(config['timeout']) + ' ' + _('sec') + ' *' )

    ######## updates
    menu_updates = Gtk.MenuItem(label=_('Update OS'))
    menu_updates.connect("activate", self.handler.check_updates, '')
    menu_updates.show()
    menu.append(menu_updates)

    if isluks:
      ######## luks-manager menu
      submenuItem3 = Gtk.MenuItem(label=_('Luks manager'))
      submenuItem3.connect("activate", self.handler.luks, '')
      submenuItem3.show()
      menu.append(submenuItem3)

    if istoxzm:
      ######## saves toggle
      if os.path.exists('/run/initramfs/shutdown'):
        toggle_label = _('Disable saves')
      elif os.path.exists('/run/initramfs/shutdown.bak'):
        toggle_label = _('Enable saves')
      else:
        toggle_label = None

      if toggle_label:
        menu_toggle_saves = Gtk.MenuItem(label=toggle_label)
        menu_toggle_saves.connect("activate", self.handler.toggle_saves, '')
        menu_toggle_saves.show()
        menu.append(menu_toggle_saves)
        self.menu_toggle_saves = menu_toggle_saves

    ######### delete backup mods
    menu_rmback = Gtk.MenuItem(label=_('Delete backup modules'))
    menu_rmback.connect("activate", self.handler.rmbak, '')
    menu.append(menu_rmback)
    self.menu_rmback = menu_rmback

    if isbackup:
      ######### switch to backup
      menu_tobackup = Gtk.MenuItem(label=_('Switch to backup'))
      menu_tobackup.connect("activate", self.handler.tobackup, '')
      menu_tobackup.show()
      menu.append(menu_tobackup)
      self.menu_tobackup = menu_tobackup

    if os.path.exists(token_file):
      menu_token = Gtk.MenuItem(label=_('Set token'))
      menu_token.connect("activate", self.handler.set_token, '')
      menu_token.show()
      menu.append(menu_token)

    ######### separator
    separ = Gtk.SeparatorMenuItem()
    menu.append(separ)
    separ.show()

    ######### exit
    menu_exit = Gtk.MenuItem(label=_('Exit'))
    menu_exit.connect("activate", self.handler.exit, '')
    menu_exit.show()
    menu.append(menu_exit)

    #########
    menu.show()
    self.ind_app.set_menu(menu)

  def run(self):
    Gtk.main()

if __name__ == '__main__':
  if len(sys.argv) > 1:
    print( sys.argv[0], '- tray applet to monitoring base parameters of Barium OS\n'
'and managing saves, please start it with no args, or by desktop file')
    quit()
  cfgdir = '/home/' + os.environ['USER'] + '/.config/barium_applet'
  if os.path.exists(cfgdir + '/dump'):
    with open(cfgdir + '/dump', 'rb') as f:
      config = pickle.load(f)
  else:
    os.makedirs(cfgdir, exist_ok=True)
    pickle_write()

  with open('/proc/cmdline', 'r') as f:
    cmdline = f.readline()

  with open('/proc/mounts', 'r') as f:
    mounts = f.readlines()

  with open('/etc/initvars', 'r') as f:
    initvars = {}
    for line in f.read().splitlines():
      initvars[line.split('=')[0]] = line.split('=', 1 )[1]

  isbackup = False
  if 'uird.from=/ROSA-SYSTEM.bak' in cmdline:
    isbackup = True

  ischanges = False
  if initvars['uird_mode'] == 'changes' in cmdline:
    ischanges = True

  isluks = False
  for f in os.listdir('/dev/mapper'):
    for line in mounts:
      if '/dev/mapper/' + f  in line:
        isluks = True
        break
    if isluks:
      break

  istoxzm = False
  if initvars['uird_mode'] == 'toxzm' and os.path.exists('/run/initramfs/remount'):
    istoxzm = True

  ishomexzm = False
  if os.path.exists(initvars['SYSMNT'] + '/layer-base/1/saves/homes.xzm') and istoxzm:
    ishomexzm = True

  if detect_DE == 'plasma':
    time.sleep(5)

  if not check_token():
    quit()
  
  # run app
  app = Applet()
  clear()
  once_timer_id = GLib.timeout_add_seconds(3 , lambda: threading_me(first_check) )
  timer_id = GLib.timeout_add(config['timeout'] * 1000, fn_getvalues, app.ind_app)
  notify_init(_('Barium applet'))
  app.run()

