#!/usr/bin/env python

#################################
#	GenPack by TheZulk	#
#				#
#	thezulk@yahoo.com	#
#################################

from wxPython.wx import *
import portage
port = portage.portagetree()
vartree = portage.vartree()
import types
import re
import os
from commands import *
from stat import *
from string import strip, replace, find

dict = {}
packDict = {}

currentPack = ''

frame = wxFrame

ID_ABOUT = 101
ID_EXIT = 102
ID_RSYNC = 103
ID_UPDATE = 104
ID_MERGE = 105
ID_UNMERGE = 106
ID_UPGRADE = 107
ID_UPDATE_WORLD = 108
ID_HELP = 109

ID_TOOL_RSYNC = 201

ROOT_ID = 0
def GetFullEbuild(Name): ## Returns location of ebuild with latest version number ##
                return strip(port.dep_bestmatch(Name))

def GetEbuildPath(strBase):  ## Returns the full path of the ebuild ##
        strBaseFinal = '/usr/portage/' + strip(strBase)
        find_package = re.compile('/')
        p = find_package.split(strip(port.dep_bestmatch(strBase)))
        strBaseFinal = strBaseFinal + "/" + p[1] + ".ebuild"
        return strBaseFinal

def GetEbuildVersion(PortageName, EbuildOrApp):
        if len(PortageName) > 1:
                GetVersion = portage.catpkgsplit(PortageName)
                if EbuildOrApp == "Ebuild":
                        if GetVersion[3] != 'r0':
                                FullVersion = GetVersion[2]+ "-" + GetVersion[3]
                        else:
                                FullVersion = GetVersion[2]
                else:
                        FullVersion = GetVersion[2]
        else:
                FullVersion = " "
        
        return FullVersion


def GetDescription(strEbuild, intVersion): ## Gets description from latest ebuild ##
        f = open(strEbuild)
        data = "temp"
        while data != "":
                data = f.readline()
                if re.search("description=\"", data.lower()):
                        dump_prefix = re.compile('DESCRIPTION="')
                        dump_suffix = re.compile('"')
                        p = dump_prefix.split(data)
                        p = dump_suffix.split(p[1])
                        result = replace(p[0], "${PV}", intVersion)
                        result = replace(result, "${pv}", intVersion)
                        result = replace(result.lower(), "${description}", "KDE "  + intVersion + " ")
                        return result


class TextBox:
	def Set(self, text):
		self.textbox = text
	def Get(self):
		return self.textbox

Text = TextBox()

class LazyTree(wxTreeCtrl): 
        '''Lazy Tree is a simple "Lazy Evaluation" tree, 
        that is, it only adds items to the tree view when 
        they are needed.''' 
        def __init__( 
                self, 
                parent, id=-1, 
                pos = wxDefaultPosition, size = wxDefaultSize, 
                style = wxTR_HAS_BUTTONS, validator = wxDefaultValidator, 
                name = "listCtrl", rootNode = None 
        ):
		self.data = rootNode
                wxTreeCtrl.__init__( self, parent, id, pos, size, style, validator, name ) 
                EVT_TREE_ITEM_EXPANDING( self, self.GetId(), self.OnExpandNode )
		EVT_TREE_SEL_CHANGED( self, self.GetId(), self.OnChange )
                self.AddRootItem( rootNode[0] )
        def OnExpandNode( self, event ): 
                ID = event.GetItem() 
                # the lazy tree deals with python objects, 
                # we call them node here... 
                node = self.GetPyData( ID)
		# print node 
                ## assert node, '''An unknown node was expanded in the LazyTree''' this check is too broad... 
                if not self.GetFirstChild( ID, 0)[0].IsOk(): 
                        # we have no children currently in the tree... 
                        if dict.has_key(node):
			    s = dict[node]
			    s.sort()
			    for child in s:
                                self.AddGenericItem( ID, child ) 
			else:
			    self.data[1].sort()
			    for child in self.data[1]: 
                                self.AddGenericItem( ID, child ) 
		event.Skip() 
 
        # primary customisation points... 
        def AddRootItem( self, node ): 
                self.AddGenericItem( None, node ) 
        def AddGenericItem( self, parentID, node ): 
                name = self.GetName( node ) 
                if parentID is None: 
                        ID = self.AddRoot( name, ) 
			self.SetItemHasChildren( ID, TRUE ) 
                else: 
		    ID = self.AppendItem( parentID, name ) 
            	    if dict.has_key(node):
		        self.SetItemHasChildren( ID, TRUE )
                self.SetPyData( ID, node ) 
        def GetName( self, node ): 
                return str(node) 
        def GetChildren( self, node ): 
                if type(node) in (types.ListType, types.TupleType): 
                        return node 
                else: 
                        return []
	def OnChange( self, data ):
		global currentPack
		item = self.GetPyData(data.GetItem())
		if packDict.has_key(item):
			currentPack = packDict[item]
			best = port.dep_bestmatch(currentPack)
			if not len(best):
				Text.Get().SetValue('Package: ' + currentPack + ' is locked away in the mask-file')
				return
			ipack = vartree.dep_bestmatch(currentPack)
			packInfo = portage.catpkgsplit(best)
			ipackInfo = portage.catpkgsplit(ipack)
			if not ipackInfo:
				ipackInfo = ['','','None',' None']
			Text.Get().SetValue('Package: ' + currentPack + '''

Description: ''' + GetDescription(GetEbuildPath(currentPack),GetEbuildVersion(GetFullEbuild(currentPack), "App")) + '''

--------In portage tree--------
''' + 'Version: ' + packInfo[2] + '''
''' + 'Revision: ' + packInfo[3][1:] + '''

-----------Installed-----------
''' + 'Version: ' + ipackInfo[2] + '''
''' + 'Revision: ' + ipackInfo[3][1:] + '''
''')


class MyFrame(wxFrame):
    def __init__(self, parent, ID, title):
	wxFrame.__init__(self,parent,ID,title,
		wxDefaultPosition, wxSize(500,350))
	self.CreateStatusBar()
	self.SetStatusText("")
	
	#toolbar = self.CreateToolBar(wxTB_DOCKABLE)
	
	#toolbar.AddTool(ID_TOOL_RSYNC, wxIcon('open', 1), wxIcon('open', 1), 'Help', 'Help me plenty')
	#toolbar.AddSeparator()
	#toolbar.Realize()

	fileMenu = wxMenu()
	fileMenu.Append(ID_ABOUT, "&About","More information about this program")
	fileMenu.AppendSeparator()
	fileMenu.Append(ID_EXIT,"E&xit","Terminate the program")

	systemMenu = wxMenu()
	systemMenu.Append(ID_RSYNC, "&Rsync", "Update the portage tree")
	systemMenu.AppendSeparator()
	systemMenu.Append(ID_UPDATE, "&Update base", "Update base system")
	systemMenu.Append(ID_UPDATE_WORLD, "Update &world", "Update all components")

	actionMenu = wxMenu()
	actionMenu.Append(ID_MERGE, "&Merge", "Merge the choosen ebuild")
	actionMenu.Append(ID_UNMERGE, "U&nmerge", "Unmerge the choosen ebuild")
	actionMenu.Append(ID_UPGRADE, "Up&grade", "Upgrade the choosen ebuild (Merge new and unmerge old)")

	menuBar = wxMenuBar()
	menuBar.Append(fileMenu, "&File")
	menuBar.Append(systemMenu, "&System")
	menuBar.Append(actionMenu, "&Action")

	self.SetMenuBar(menuBar)

	self.control = wxTextCtrl(self , 1, style=wxTE_MULTILINE)
	self.control.SetValue('''Package: ---
Version in portage tree: ---
Revision: ---
Installed version: ---''')
	Text.Set(self.control)

	# Load the portage tree into dictionaries
	for text in portage.categories:
		dir = '/usr/portage/' + text
		if os.path.isdir(dir):
			a = os.listdir(dir)
			a.sort()
			dict[text] = a
			for package in a:
				packDict[package] = text + '/' + package
	
	# Preload the bestmatch list
	port.dep_bestmatch(packDict[packDict.keys()[0]])
	vartree.dep_bestmatch(packDict[packDict.keys()[0]])

	self.sizer = wxBoxSizer(wxHORIZONTAL)
	self.tree = LazyTree(self, rootNode = ["Packages",dict.keys()])
	self.sizer.Add(self.tree, 2, wxEXPAND)
	self.sizer.Add(self.control,5,wxEXPAND)
	self.SetSizer(self.sizer)
	self.SetAutoLayout(true)
	#self.sizer.Fit(self)


	EVT_MENU(self,ID_ABOUT,self.OnAbout)
	EVT_MENU(self,ID_EXIT,self.OnExit)
	EVT_MENU(self,ID_RSYNC,self.OnRsync)
	EVT_MENU(self,ID_UPDATE,self.OnUpdate)
	EVT_MENU(self,ID_MERGE,self.OnMerge)
	EVT_MENU(self,ID_UNMERGE,self.OnUnMerge)
	EVT_MENU(self,ID_UPGRADE,self.OnUpgrade)
	EVT_MENU(self,ID_UPDATE_WORLD,self.OnUpdateWorld)
	EVT_MENU(self,ID_HELP,self.OnHelp)
	
    def OnAbout(self, event):
	dlg = wxMessageDialog(self, "This program is going to be\n"
				    "a GUI tool for the portage tools.\n\n"
				    "                made by TheZulk",

				    "About GenPack", wxOK|wxICON_INFORMATION)
	dlg.ShowModal()
	dlg.Destroy()

    def OnExit(self, event):
	self.Close(true)

    def OnRsync(self, event):
        os.system("xterm -T 'Doing rsync' -e /usr/bin/env emerge rsync") 

    def OnUpdate(self, event):
       os.system("xterm -T 'Updating base system' -e /usr/bin/env emerge update")

    def OnMerge(self, event):
	global currentPack
	if not len(currentPack): return
	print currentPack
        mycommand = "xterm -T 'Merging " + currentPack + "' -e /usr/bin/env emerge " + currentPack
        os.system(mycommand)

    def OnUnMerge(self, event):
        ipack = vartree.dep_bestmatch(currentPack)
        ipackInfo = portage.catpkgsplit(ipack)
	if ipackInfo[3] == 'r0':
		ipackInfo[3] = ''
	else:
		ipackInfo[3] = '-'+ipackInfo[3]
        os.system("xterm -T 'Unmerging " + currentPack + "' -e /usr/bin/env ebuild " + '/usr/portage/' + currentPack + '/' + ipackInfo[1] + "-" + ipackInfo[2]  + ipackInfo[3] + '.ebuild' + ' unmerge')

    def OnUpgrade(self, event):
	pack = port.dep_bestmatch(currentPack)
        ipack = vartree.dep_bestmatch(currentPack)
	if not ipack:
		return
	packInfo = portage.catpkgsplit(pack)
        ipackInfo = portage.catpkgsplit(ipack)
	if ipackInfo[2] == packInfo[2]:
		if ipackInfo[3] == packInfo[3]:
			return

	if ipackInfo[3] == 'r0':
		ipackInfo[3] = ''
	else:
		ipackInfo[3] = '-'+ipackInfo[3]
	unInstallCommand = "xterm -T 'Upgrading " + currentPack + "' -e /usr/bin/env ebuild " + '/usr/portage/' + currentPack + '/' + ipackInfo[1] + "-" + ipackInfo[2]  + ipackInfo[3] + '.ebuild' + ' unmerge'
        os.system("xterm -T 'Upgrading " + currentPack + "' -e /usr/bin/env emerge " + currentPack)
	os.system(unInstallCommand)

    def OnUpdateWorld(self, event):
        os.system("xterm -T 'Updating world' -e /usr/bin/env emerge update --world")

    def OnHelp(self, event):
	dlg = wxMessageDialog(self, "You really need help?\n"
				    "\n"
				    "Please e-mail me at thezulk@yahoo.com",
				    "About GenPack", wxOK|wxICON_INFORMATION)
	dlg.ShowModal()
	dlg.Destroy()

if __name__ == '__main__':
	class MyApp(wxApp):
	    def OnInit(self):
		global frame
		frame = MyFrame(NULL,-1,"GenPack - The portage GUI")
		frame.Show(true)
		self.SetTopWindow(frame)
		return true

	app = MyApp(0)
	app.MainLoop()


