#!/usr/bin/env python3

#Copyright 2025 mycophobia. Licensed under the GNU GPL version 3. A copy can be found enclosed with the source code, or here:
#https://www.gnu.org/licenses/gpl-3.0.en.html

import wx

# begin wxGlade: dependencies
# end wxGlade

# begin wxGlade: extracode
# end wxGlade


class AFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: AFrame.__init__
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((550, 600))
        self.SetTitle("AppManager")

        self.panel_1 = wx.Panel(self, wx.ID_ANY)

        sizer_2 = wx.BoxSizer(wx.VERTICAL)

        self.list_ctrl_2 = wx.ListCtrl(self.panel_1, wx.ID_ANY, style=wx.LC_NO_HEADER | wx.LC_REPORT | wx.LC_SINGLE_SEL)
        self.list_ctrl_2.AppendColumn("A", format=wx.LIST_FORMAT_LEFT, width=-1)
        sizer_2.Add(self.list_ctrl_2, 1, wx.EXPAND, 0)

        self.search_ctrl_2 = wx.SearchCtrl(self.panel_1, wx.ID_ANY, "")
        self.search_ctrl_2.ShowCancelButton(True)
        self.search_ctrl_2.SetDescriptiveText("Type search terms and press Enter")
        sizer_2.Add(self.search_ctrl_2, 0, wx.EXPAND, 0)

        self.info_button = wx.Button(self.panel_1, wx.ID_ANY, "Show Information")
        sizer_2.Add(self.info_button, 0, wx.EXPAND, 0)

        self.install_button = wx.Button(self.panel_1, wx.ID_ANY, "Install Application")
        sizer_2.Add(self.install_button, 0, wx.EXPAND, 0)

        static_line_1 = wx.StaticLine(self.panel_1, wx.ID_ANY)
        sizer_2.Add(static_line_1, 0, wx.EXPAND, 0)

        self.update_button = wx.Button(self.panel_1, wx.ID_ANY, "Update System")
        sizer_2.Add(self.update_button, 0, wx.EXPAND, 0)

        static_line_2 = wx.StaticLine(self.panel_1, wx.ID_ANY)
        sizer_2.Add(static_line_2, 0, wx.EXPAND, 0)

        debinstall = wx.StaticText(self.panel_1, wx.ID_ANY, "Drag and drop a Debian package (file ending in \".deb\") onto this window to install it.")
        debinstall.SetMinSize((366, 30))
        sizer_2.Add(debinstall, 0, wx.EXPAND, 0)

        static_line_3 = wx.StaticLine(self.panel_1, wx.ID_ANY)
        sizer_2.Add(static_line_3, 0, wx.EXPAND, 0)

        self.uninstall = wx.StaticText(self.panel_1, wx.ID_ANY, "Drag and drop an application from the Menu onto this window to uninstall it.")
        self.uninstall.SetMinSize((366, 30))
        sizer_2.Add(self.uninstall, 0, wx.EXPAND, 0)

        self.panel_1.SetSizer(sizer_2)

        self.Layout()

        self.list_ctrl_2.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.disable_install_button)
        self.list_ctrl_2.Bind(wx.EVT_LIST_ITEM_SELECTED, self.enable_install_button)
        self.search_ctrl_2.Bind(wx.EVT_TEXT_ENTER, self.do_search)
        self.info_button.Bind(wx.EVT_BUTTON, self.show_info)
        self.install_button.Bind(wx.EVT_BUTTON, self.install_app)
        self.update_button.Bind(wx.EVT_BUTTON, self.update_system)
        # end wxGlade

    def disable_install_button(self, event):  # wxGlade: AFrame.<event_handler>
        print("Event handler 'disable_install_button' not implemented!")
        event.Skip()

    def enable_install_button(self, event):  # wxGlade: AFrame.<event_handler>
        print("Event handler 'enable_install_button' not implemented!")
        event.Skip()

    def do_search(self, event):  # wxGlade: AFrame.<event_handler>
        print("Event handler 'do_search' not implemented!")
        event.Skip()

    def show_info(self, event):  # wxGlade: AFrame.<event_handler>
        print("Event handler 'show_info' not implemented!")
        event.Skip()

    def install_app(self, event):  # wxGlade: AFrame.<event_handler>
        print("Event handler 'install_app' not implemented!")
        event.Skip()

    def update_system(self, event):  # wxGlade: AFrame.<event_handler>
        print("Event handler 'update_system' not implemented!")
        event.Skip()

# end of class AFrame

class InfoFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: InfoFrame.__init__
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((580, 500))
        self.SetTitle("Package Information")

        self.info_box = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_LEFT | wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_WORDWRAP)
        self.Layout()
        # end wxGlade

# end of class InfoFrame

class UpdateDialog(wx.Dialog):
    def __init__(self, *args, **kwds):
        # begin wxGlade: UpdateDialog.__init__
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE
        wx.Dialog.__init__(self, *args, **kwds)
        self.SetTitle("Update System")

        sizer_1 = wx.BoxSizer(wx.VERTICAL)

        label_1 = wx.StaticText(self, wx.ID_ANY, "AppManager needs to update your system before it can run for the first time.")
        sizer_1.Add(label_1, 0, 0, 0)

        sizer_2 = wx.StdDialogButtonSizer()
        sizer_1.Add(sizer_2, 0, wx.ALIGN_RIGHT | wx.ALL, 4)

        self.button_OK = wx.Button(self, wx.ID_OK, "")
        self.button_OK.SetDefault()
        sizer_2.AddButton(self.button_OK)

        sizer_2.Realize()

        self.SetSizer(sizer_1)
        sizer_1.Fit(self)

        self.SetAffirmativeId(self.button_OK.GetId())

        self.Layout()
        # end wxGlade

# end of class UpdateDialog

from os import listdir, popen, system
from os.path import exists, expanduser

class UninstallDrop(wx.FileDropTarget):
    def __init__(self, uninstallcallback, debcallback):
        super().__init__()
        self.uninstallcallback = uninstallcallback
        self.debcallback = debcallback

    def OnDropFiles(self, x, y, filenames):
        if filenames[0].lower().endswith('.desktop'):
            self.uninstallcallback(filenames[0])
        elif filenames[0].lower().endswith('.deb'):
            self.debcallback(filenames[0])
        return True

class MainWindow(AFrame):
    def __init__(self, *args, **kwds):
        super().__init__(*args, **kwds)
        self.disable_install_button(None)
        target = UninstallDrop(self.uninstall_callback, self.debinstall_callback)
        self.SetDropTarget(target)
        listpath = expanduser('~')+'/.config/appmanager_desktoppackages'
        if not exists(listpath):
            self.first_run()
    
    def first_run(self):
        dialog = UpdateDialog(self)
        dialog.ShowModal()
        self.update_system(None)
    
    def enable_install_button(self, event):
        self.info_button.Enable()
        self.install_button.Enable()
    
    def disable_install_button(self, event):
        self.info_button.Disable()
        self.install_button.Disable()
    
    def do_search(self, event):
        self.list_ctrl_2.ClearAll()
        self.list_ctrl_2.InsertColumn(0, 'something')
        query = self.search_ctrl_2.GetValue()
        results = popen('appmanager_checkifdesktop %s'%query).readlines()
        final_results = []
        for line in results:
            item = line.strip().ljust(80)
            final_results.append(item)
        
        final_results = sorted(final_results, reverse=True)
        for item in final_results:
            self.list_ctrl_2.InsertItem(0, item)
        self.list_ctrl_2.SetColumnWidth(0, -1)
    
    def show_info(self, event):
        selection = self.list_ctrl_2.GetFirstSelected()
        package = self.list_ctrl_2.GetItem(selection).GetText().split(' - ')[0].strip()
        infoframe = InfoFrame(None, wx.ID_ANY, "")
        fpkginfo = []
        pkginfo = popen('apt-cache show %s'%package).readlines()
        for line in pkginfo:
            if line.strip().split() != []:
                if not line.strip().split()[0].endswith(':') and '::' not in line:
                    fpkginfo.append(line)
        infoframe.info_box.write(''.join(fpkginfo))
        infoframe.Show()
        
    def install_app(self, event):
        selection = self.list_ctrl_2.GetFirstSelected()
        package = self.list_ctrl_2.GetItem(selection).GetText().split(' - ')[0].strip()
        system('xterm -T "Installing Package %s" -hold -e "sudo apt install %s; echo Done. You may close this window."'%(package, package))
    
    def update_system(self, event):
        system('xterm -T "Updating System" -hold -e "sudo apt update; sudo apt-file update; appmanager_getdesktoplist; sudo apt dist-upgrade; echo Done. You may close this window."')
    
    def uninstall_callback(self, dfile):
        system('xterm -T "Uninstalling an application" -hold -e "appmanager_uninstall %s; echo Done. You may close this window."'%dfile)
    
    def debinstall_callback(self, dfile):
        dfile = dfile.replace(' ','\\ ')
        system('xterm -T "Installing Debian Package" -hold -e "sudo apt install %s; echo Done. You may close this window."'%dfile)
    
class AppManager(wx.App):
    def OnInit(self):
        self.frame_1 = MainWindow(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame_1)
        self.frame_1.Show()
        return True

if __name__ == "__main__":
    appmanager = AppManager(0)
    appmanager.MainLoop()
