#
#  AddOnManager for OE 2.5
#  Coded by Dr.Best (c)2010 / dre (c)2016
#  Support: www.dreambox.tools
#
#  This plugin is licensed under the Creative Commons 
#  Attribution-NonCommercial-ShareAlike 3.0 Unported 
#  License. To view a copy of this license, visit
#  http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative
#  Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
#
#  This plugin is NOT free software. It is open source, you are allowed to
#  modify it (if you keep the license), but it may not be commercially 
#  distributed.
#

from Components.ActionMap import ActionMap, HelpableActionMap, NumberActionMap
from Components.AVSwitch import AVSwitch
from Components.ConfigList import ConfigListScreen
from Components.DreamInfoHandler import InfoHandler, InfoHandlerParseError
from Components.Label import Label, MultiColorLabel
from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaBlend
from Components.Pixmap import Pixmap
from Components.Sources.List import List
from Components.config import config, ConfigSubsection, ConfigOnOff, getConfigListEntry
from Screens.ChoiceBox import ChoiceBox
from Screens.Console import Console
from Screens.HelpMenu import HelpableScreen
from Screens.MessageBox import MessageBox
from Screens.Screen import Screen
from Plugins.Plugin import PluginDescriptor
from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE, fileExists, SCOPE_CURRENT_SKIN, SCOPE_METADIR
from Tools.HardwareInfo import HardwareInfo
from Tools.LoadPixmap import LoadPixmap
from Tools.NumericalTextInput import NumericalTextInput
from enigma import gFont, eConsoleAppContainer, eNetworkManager, ePicLoad, ePoint, eSize
from operator import itemgetter
from twisted.web import client
import xml.sax
from . import _
import re

INSTALLED = re.compile('^\s*Installed\:\s(.*?)$')
CANDIDATE = re.compile('^\s*Candidate\:\s(.*?)$')
PACKAGE = re.compile('^enigma2\-((plugin\-(.*?)|skin|piconmapper|cams)\-([a-zA-Z0-9\-\.]*))\:$')
NOTRELEVANTPACKAGE = re.compile('^enigma2\-(.*?)\:$')

config.plugins.addonmanager = ConfigSubsection()
config.plugins.addonmanager.usesplitscreen = ConfigOnOff(default = False) 

def main(session,**kwargs):
    session.open(MerlinDownloadBrowser)
    
def openAddonManager(session, args, **kwargs):
	session.open(MerlinDownloadBrowser)

def Plugins(**kwargs):
    return [PluginDescriptor(name="Addon Manager", description=_("Manage additional software"), where = [PluginDescriptor.WHERE_PLUGINMENU, PluginDescriptor.WHERE_EXTENSIONSMENU ], fnc=main, icon = "plugin.png"), PluginDescriptor(name="Addon Manager", where=[PluginDescriptor.WHERE_SOFTWAREMANAGER], fnc={"SoftwareSupported":openAddonManager,"menuEntryName":_("AddOnManager"),"menuEntryDescription":_("Plugin to install, update and uninstall additional software for Merlin")})]

class MerlinDownloadBrowser(Screen, HelpableScreen):
	#Skinner: 
	# - menu has a dummy "default" style element which is NOT used but must be there. So, it is set to a size of 0,0
	# - list requires an offset for the "split" style. The list element starts at 10,10 but is hidden behind the menu
	skin = """
		<screen name="MerlinDownloadBrowser" position="center,55" size="950,650">
			<widget font="Regular;20" halign="center" name="text" position="10,10" size="930,595" valign="center" zPosition="3"/>
			<widget source="menu" render="Listbox" position="10,10" size="250,595" scrollbarMode="showOnDemand" zPosition="2">
				<convert type="TemplatedMultiContent">
					{"templates": {
						"default":(65, [
							MultiContentEntryText(pos=(595,0), size=(0,0), text=0),
						]),
						"split": (65,						
						[
							MultiContentEntryPixmapAlphaBlend(pos=(5,20), size=(25,25), png=1),
							MultiContentEntryText(pos=(50,20), size=(200,30), font=0, text=0),
						]),
					},
						"fonts": [gFont("Regular",20),gFont("Regular",14)],
					}
				</convert>
			</widget>				
			<widget source="list" render="Listbox" position="10,10" size="930,595" scrollbarMode="showOnDemand" zPosition="1">
				<convert type="TemplatedMultiContent">
					{"templates": {
						"default": (65,
						[
							MultiContentEntryPixmapAlphaBlend(pos=(5,20), size=(25,25), png=1),
							MultiContentEntryText(pos=(130,20), size=(800,30), font=0, text=0),
							MultiContentEntryText(pos=(100,5), size=(830,25), font=0, text=2),
							MultiContentEntryText(pos=(100,30), size=(830,20), font=1, text=3),
							MultiContentEntryText(pos=(100,47), size=(830,20), font=1, text=4),
							MultiContentEntryPixmapAlphaBlend(pos=(20,12), size=(14,14), png=5),						
						]),
						"split": (65,
						[
							MultiContentEntryText(pos=(100,5), size=(570,25), font=0, text=2),
							MultiContentEntryText(pos=(100,30), size=(570,20), font=1, text=3),
							MultiContentEntryText(pos=(100,47), size=(570,20), font=1, text=4),
							MultiContentEntryPixmapAlphaBlend(pos=(20,12), size=(14,14), png=5),
						]),
					},	
						"fonts": [gFont("Regular",20),gFont("Regular",14)],
					}
				</convert>
			</widget>
			<ePixmap alphatest="blend" pixmap="skin_default/buttons/red.png" position="10,610" size="30,30" transparent="1" />
			<widget font="Regular;18" name="redtext" position="50,610" size="160,30" valign="center" zPosition="3"/>
			<ePixmap alphatest="blend" pixmap="skin_default/buttons/yellow.png" position="220,610" size="30,30" transparent="1" />
			<widget font="Regular;18" name="yellowtext" position="260,610" size="240,30" valign="center" zPosition="3"/>			
			<ePixmap alphatest="blend" pixmap="skin_default/buttons/blue.png" position="510,610" size="30,30" transparent="1" />			
			<widget font="Regular;18" name="bluetext" position="550,610" size="180,30" valign="center" zPosition="3"/>
			<ePixmap alphatest="blend" pixmap="skin_default/icons/info.png" position="750,610" size="40,30" transparent="1" />												
			<ePixmap alphatest="blend" pixmap="skin_default/icons/menu.png" position="800,610" size="40,30" transparent="1" />	
			<ePixmap alphatest="blend" pixmap="skin_default/icons/pvr.png" position="850,610" size="40,30" transparent="1" />	
			<ePixmap alphatest="blend" pixmap="skin_default/icons/help.png" position="900,610" size="40,30" transparent="1" />	
		</screen>"""
	
	def __init__(self, session, args = None):
		Screen.__init__(self, session)
		HelpableScreen.__init__(self)

		self["WizardActions"] = HelpableActionMap(self, "WizardActions",
		{
			"ok": 		(self.go,_("Execute an action")),
			"back":		(self.close,_("Close plugin")),
			"up":		(self.moveUp,_("Move up")),
			"down":		(self.moveDown,_("Move down")),
			"left":		(self.pageUp,_("Page up")),
			"right":	(self.pageDown,_("Page down")),
			"video":	(self.savePackages, _("Back up installed packages")),
		}, -1)

		self["ChannelSelectEPGActions"] = HelpableActionMap(self, "ChannelSelectEPGActions",
		{
			"showEPGList":	(self.showInfo,_("Show package info")),
		}, -1)

		self["ChannelSelectBaseActions"] = HelpableActionMap(self, "ChannelSelectBaseActions",
		{
			"nextMarker":	(self.nextCategory,_("Change to next category in split mode")),
			"prevMarker": 	(self.previousCategory,_("Change to previous category in split mode")),
			"nextBouquet":	(self.previousCategory,_("Change to previous category in split mode")),
			"prevBouquet": 	(self.nextCategory,_("Change to next category in split mode")),	
		}, -1)
		
		self["MenuActions"] = HelpableActionMap(self,"MenuActions", 
		{
			"menu":	(self.openConfig,_("Open config")),
		}, -1)
		
		self["ColorActions"] = HelpableActionMap(self, "ColorActions",
		{
			"blue": (self.showDependencies, _("Show package dependencies")),
			"yellow": (self.toggleHoldMarker, _("Toggle hold/unhold package")),
			"red":		(self.toggleInstalledOnly, _("Toggle installed packages only")),
		}, -1)

		self["NumberActions"] = NumberActionMap(["NumberActions","InputAsciiActions"],
		{
				"gotAsciiCode": self.keyAsciiCode,
				"0": self.keyNumberGlobal,
				"1": self.keyNumberGlobal,
				"2": self.keyNumberGlobal,
				"3": self.keyNumberGlobal,
				"4": self.keyNumberGlobal,
				"5": self.keyNumberGlobal,
				"6": self.keyNumberGlobal,
				"7": self.keyNumberGlobal,
				"8": self.keyNumberGlobal,
				"9": self.keyNumberGlobal,
		})

		self.numericalTextInput = NumericalTextInput()
		self.numericalTextInput.setUseableChars(u'1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ')
		
		self.container = eConsoleAppContainer()
		self.appClosed_testconn = self.container.appClosed.connect(self.runFinished)
		self.dataAvail_testconn = self.container.dataAvail.connect(self.dataAvail)
		self.stdErrAvail_testconn = self.container.stderrAvail.connect(self.displayError)
		self.hasColorDisplay = HardwareInfo().get_device_name() in ("dm900","dm920","dm820")
		
		self.onLayoutFinish.append(self.startRun)
		self.onShown.append(self.setWindowTitle)
		
		self.list = []
		self["list"] = List(self.list)
		self.expanded = []
		self.menu = []
		self["menu"] = List(self.menu)
		self["redtext"] = Label(_("Installed only"))
		self["yellowtext"] = Label(_("Hold package"))
		self["bluetext"] = Label(_("Show dependencies"))

		self.index = 0
		self.menuIndex = 0
		
		self["text"] = Label(_("Downloading addon information. Please wait..."))
		self["text"].show()
		
		self.run = 0
		self.addonList=[]
		self.remainingData = ""
		self.packageList = []
		self.heldPackages = []
		self.linesToProcess = []
		self.installedDict = {}
		self.updatableDict = {}

		
		self.installedOnly = False
		self.listResized = False

		self["list"].onSelectionChanged.append(self.updateSummary)
		self["list"].onSelectionChanged.append(self.updateButtonText)
		self.onShown.append(self.updateSummary)
		self.onLayoutFinish.append(self.setLayout)

	def savePackages(self):
		cmdList = ["echo 'Creating /data/packages.bak'", "(cd /var/lib/dpkg/info && ls -1 *.list) | sed -e 's,\.list$,,' > /data/packages.bak"]

		self.session.open(Console, cmdlist = cmdList)
		
	def updateButtonText(self):
		if len(self.list):
			if self["list"].getCurrent()[8]:
				self["yellowtext"].setText(_("Unhold package"))
			else:
				self["yellowtext"].setText(_("Hold package"))

	def toggleInstalledOnly(self):
		if self.installedOnly:
			self.installedOnly = False
			self["redtext"].setText(_("Installed only"))
		else:
			self.installedOnly = True
			self["redtext"].setText(_("All"))
		self.createList()

	def displayError(self, data):
		self["text"].setText(data)

	def keyAsciiCode(self):
		unichar = unichr(getPrevAsciiCode())
		charstr = unichar.encode("utf-8")
		if len(charstr) == 1:
			index = self.getFirstMatchingEntry(charstr[0])
			if index is not None:
				self["list"].setIndex(index)

	def keyNumberGlobal(self, number):
		unichar = self.numericalTextInput.getKey(number)
		charstr = unichar.encode("utf-8")
		if len(charstr) == 1:
			index = self.getFirstMatchingEntry(charstr[0])
			if index is not None:
				self["list"].setIndex(index)
			
	def getFirstMatchingEntry(self, char):
		for i in range(len(self.list)):
			if self.list[i][2].upper().startswith(char):
				return i
	
	def setLayout(self):
		if config.plugins.addonmanager.usesplitscreen.value:
			self["list"].style = "split"
			self["menu"].style = "split"
			self["menu"].show()
			self["menu"].setSelectionEnabled(False)
			self["list"].setSelectionEnabled(True)			
		else:
			self["list"].style = "default"
			self["menu"].style = "default"
			self.expanded = []
			self["menu"].hide()
		self.createList()
	
	def openConfig(self):
		self.session.openWithCallback(self.setLayout, AddonManagerConfigScreen)

	def pageUp(self):
		self["list"].moveSelection("pageUp")
		
	def pageDown(self):
		self["list"].moveSelection("pageDown")
		
	def moveUp(self):
		self["list"].moveSelection("moveUp")
		
	def moveDown(self):
		self["list"].moveSelection("moveDown")

	def nextCategory(self):
		if config.plugins.addonmanager.usesplitscreen.value:
			self.expanded = []		
			if self.menuIndex<len(self.menu)-1:
				self.menuIndex += 1
			else:
				self.menuIndex = 0
			self["menu"].setIndex(self.menuIndex)
			self.createList()		
			
	def previousCategory(self):
		if config.plugins.addonmanager.usesplitscreen.value:
			self.expanded = []
			if self.menuIndex>0:
				self.menuIndex -= 1
			else:
				self.menuIndex = len(self.menu)-1
			self["menu"].setIndex(self.menuIndex)
			self.createList()

	def showInfo(self):
		sel = self["list"].getCurrent()
		metaPath = resolveFilename(SCOPE_METADIR)
		infoFile = "%s/plugin_%s.xml" %(metaPath, sel[2])

		if fileExists(infoFile):
			self.packageDetails = []
			handler = InfoHandler(False, metaPath + "/")
			try:
				xml.sax.parse(infoFile, handler)
				for entry in handler.list:
					self.packageDetails.append((entry,file))

				if len(self.packageDetails) > 0:					
					self.package = self.packageDetails[0]
					self.session.open(DetailInfoScreen, self.package)
			except InfoHandlerParseError:
				print "file", infoFile, "ignored due to errors in the file"
				
			
		else:
			self.session.open(MessageBox, _("No plugin information available"), MessageBox.TYPE_ERROR)	

	def showDependencies(self):
		self.executeAction("dependencies")
		
	def toggleHoldMarker(self):
		self.executeAction("holdunhold")
		
	def runFinished(self, retval):
		# check whether the command was executed successfully
		if retval == 0:
			if self.run == 0:
				#apt-get update
				self.run = 1
				self.container.execute(self.commandList[self.run])
			elif self.run == 1:
				#apt-mark showhold
				self.run = 2
				self.container.execute(self.commandList[self.run])
			elif self.run == 2:
				#apt-cache policy
				for line in self.linesToProcess:
					if line == '':
						continue
					if PACKAGE.match(line) is not None:
						groups = PACKAGE.match(line).groups()
						category = ""
						if groups[2] is not None:
							category = groups[2]
							if category == "skin":
								category = "skins"
						else:
							category = groups[1]
						packageName = "enigma2-" + groups[0]
						displayName = groups[3]
						if displayName.endswith("-meta"):
							packageName = "---"
						else:
							self.packageList.append((packageName, category, displayName))
					elif NOTRELEVANTPACKAGE.match(line) is not None:
						packageName = "---"
					elif packageName != "---" and INSTALLED.match(line) is not None:
						packageInstalled = INSTALLED.match(line).group(1)
						if packageInstalled == "(none)":
							packageInstalled = _("not installed")
						self.installedDict[packageName] = packageInstalled
					elif packageName != "---" and CANDIDATE.match(line) is not None:
						packageCandidate = CANDIDATE.match(line).group(1)
						if packageCandidate == "(none)":
							packageCandidate = _("no version available")
						self.updatableDict[packageName] = packageCandidate
				
				
				if len(self.packageList) > 0:
					self["text"].hide()
					
					self.createList()
	
	def createList(self):
		self.list = []
		self.menu = []
		self.addonList = []
		if fileExists(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/folder.png")):
			expandableIcon = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/folder.png"))
		else:
			expandableIcon = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/folder.png"))
		
		if fileExists(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/lock_on.png")):
			expandedIcon = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/lock_on.png"))
		else:
			expandedIcon = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/lock_on.png"))
		
		if fileExists(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/verticalline-plugins.png")):
			verticallineIcon = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/verticalline-plugins.png"))
		else:
			verticallineIcon = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/verticalline-plugins.png"))
		
		installedIcon = LoadPixmap(resolveFilename(SCOPE_PLUGINS, "/usr/share/enigma2/Merlin/green.png"))
		notinstalledIcon = LoadPixmap(resolveFilename(SCOPE_PLUGINS, "/usr/share/enigma2/Merlin/red.png"))
		updateIcon = LoadPixmap(resolveFilename(SCOPE_PLUGINS, "/usr/share/enigma2/Merlin/blue.png"))	
		heldIcon = LoadPixmap(resolveFilename(SCOPE_PLUGINS, "/usr/share/enigma2/Merlin/yellow.png"))

		self.categories = []
		
		for i in range(len(self.packageList)):
			try:
				category = self.packageList[i][1]
				packagename = self.packageList[i][0]
				
				currentVersionInfo = self.installedDict.get(packagename)
				updatableVersionInfo = self.updatableDict.get(packagename)
				
				if currentVersionInfo == _("not installed") and updatableVersionInfo == _("no version available"):
					continue

				if not category in self.categories:
					self.categories.append(category)

				if currentVersionInfo is not None and currentVersionInfo != _("not installed") and currentVersionInfo != updatableVersionInfo and updatableVersionInfo is not None:
					text = _("%s -> updatable to %s") %(currentVersionInfo, updatableVersionInfo)
					pngstatus = updateIcon
					status = 2
				elif currentVersionInfo is not None and currentVersionInfo != _("not installed"):
					text = _("Installed package version: %s") %(currentVersionInfo)
					pngstatus = installedIcon
					status = 1
				else:
					text = _("Package version: %s") %(updatableVersionInfo)
					pngstatus = notinstalledIcon
					status = 0

				held = False	
				if packagename in self.heldPackages:
					held = True
					pngstatus = heldIcon
				if self.installedOnly and status == 0:
					continue				

				# category of the package, shortened name of the package, description of the package, info text, status icon, status code, package name, package hold information
				self.addonList.append((category, self.packageList[i][2], "", text, pngstatus, status, packagename, held))
			except:
				print "error"
				pass
				
		#sort the list by the packagename
		self.addonList.sort(key=itemgetter(1))	
		
		#sort the list by the category
		self.categories.sort(key=itemgetter(0))

		if config.plugins.addonmanager.usesplitscreen.value:
			self.expanded = []
			if len(self.categories) >0:
				self.expanded.append(self.categories[self.menuIndex])
		
		for item in self.categories:
			if item in self.expanded:
				#category is opened
				if config.plugins.addonmanager.usesplitscreen.value:
					self.menu.append((item, expandedIcon))
				else:
					self.list.append((item, expandedIcon, "", "", "", None, "","", ""))
				for package in self.addonList:
					if package[0] == item:
						#package is held
						if package[7]:
							packagename = package[1] + " (" + _("held") + ")"
						else:
							packagename = package[1]
						self.list.append(("", None, packagename, package[2], package[3], package[4], package[5], package[6], package[7]))
			else:
				#category is closed
				if config.plugins.addonmanager.usesplitscreen.value:
					self.menu.append((item, expandableIcon))
				else:
					self.list.append((item, expandableIcon, "", "", "", None, "", "",""))
		self["list"].updateList(self.list)
		self["list"].setIndex(self.index)
		self.updateButtonText()
		self.updateSummary()
		
		width_menu = self["menu"].master.master.instance.csize().width()
		if config.plugins.addonmanager.usesplitscreen.value:
			if not self.listResized:
				self.width_list_org = self["list"].master.master.instance.csize().width()
				self.xpos_list_org = self["list"].master.master.instance.position().x()

			self["menu"].setList(self.menu)
			self["menu"].setIndex(self.menuIndex)
			
			if not self.listResized: 
				self.listResized = True
				width_new =  self.width_list_org - width_menu
				self["list"].master.master.instance.resize(eSize(width_new, self["list"].master.master.instance.csize().height()))
			self["list"].master.master.instance.move(ePoint(self["menu"].master.master.instance.position().x() + width_menu, self["list"].master.master.instance.position().y()))
		else:
			# reset position in case the user switched the setting
			if self.listResized:
				self.listResized = False
				self["list"].master.master.instance.resize(eSize(self.width_list_org, self["list"].master.master.instance.csize().height()))
				self["list"].master.master.instance.move(ePoint(self.xpos_list_org, self["list"].master.master.instance.position().y()))

	def dataAvail(self, str):
		if self.run > 0:
			str = self.remainingData + str
			lines = str.split("\n")
			
			if len(lines[-1]):
				self.remainingData = lines[-1]
				lines = lines[0:-1]
			else:
				self.remainingData = ""

			if self.run == 1:
				#apt-mark showhold
				if len(self.heldPackages) == 0:
					self.heldPackages = [x for x in lines if x != '']
				else:
					for x in lines:
						if x != '' and x not in self.heldPackages:
							self.heldPackages.append(x)
				
			if self.run == 2:
				#apt-cache policy
				# don't process data here yet as it's quite a lot of data
				self.linesToProcess.extend(lines)

	def createSummary(self):
		return AddOnManagerLCDScreen
		
	def updateSummary(self):
		text = ""
		state = None
		if len(self.list):
			selection = self["list"].getCurrent()

			if selection[0] == "":
				# package
				text = selection[2]
				if self.hasColorDisplay:
					state = selection[6]
					if selection[8]:
						state = 3
			else:
				# category
				text = selection[0]
				if self.hasColorDisplay:
					state = 4
		
		self.summaries.setText(text, state)

	def go(self):
		self.index = self["list"].index
		sel = self["list"].getCurrent()
		
		if sel is None:
			return

		if sel[0] != "": # category
			if sel[0] in self.expanded:
				self.expanded.remove(sel[0])
			else:
				self.expanded.append(sel[0])
			self.createList()
		else: # package
			if sel[6] == 0:
				self.session.openWithCallback(self.runInstall, MessageBox, _("Do you really want to download\nthe addon \"%s\"?") % sel[2])
			elif sel[6] == 1:
				self.session.openWithCallback(self.runInstall, MessageBox, _("Do you really want to REMOVE\nthe addon \"%s\"?") % sel[2])
			elif sel[6] == 2:
				self.session.openWithCallback(self.runDeleteUpdateCallBack, ChoiceBox, title=_("The addon %s is already installed and an update is available.\nWhat do you want to do?") % sel[2], list = [(_("Update package"), 0), (_("Delete package"), 1)], windowTitle = _("AddOnManager"))

	def runInstall(self, val):
		if val:
			if self["list"].getCurrent()[6] != 1:
				self.executeAction("install")
			else:
				self.executeAction("remove")
	
	def runDeleteUpdateCallBack(self, answer):
		if answer is not None:
			if answer[1] == 0:
				self.executeAction("install")
			elif answer[1] == 1:
				self.executeAction("remove")

	def executeAction(self, action=None):
		self.index = self["list"].index
		if action == "install":
			self.session.openWithCallback(self.installFinished, Console, cmdlist = ["apt-get -f --allow-unauthenticated install " + self["list"].getCurrent()[7]])
		elif action == "remove":
			self.session.openWithCallback(self.installFinished, Console, cmdlist = ["apt-get -y autoremove " + self["list"].getCurrent()[7]])
		elif action == "dependencies":
			self.session.open(Console, cmdlist = ["apt-cache depends " + self["list"].getCurrent()[7]])
		elif action == "holdunhold":
			if self["list"].getCurrent()[6] != 0:
				param = "hold"
				if self["list"].getCurrent()[8]:
					param = "unhold"
				self.session.openWithCallback(self.installFinished, Console, cmdlist = ["apt-mark %s %s" %(param, self["list"].getCurrent()[7])])
			
	def setWindowTitle(self):
		self.setTitle(_("Merlin AddOn Browser"))

	def startRun(self):
		self["text"].show()
		self.commandList = ["apt-get update","apt-mark showhold","apt-cache policy enigma2-[a-z0-9]"]
		self.container.execute(self.commandList[self.run])

	def installFinished(self):
		self.run = 1
		self.packageList = []
		self.linesToProcess = []
		self.installedDict = {}
		self.updatableDict = {}
		self.heldPackages = []
		self.container.execute(self.commandList[self.run])

class DetailInfoScreen(Screen):
	skin = """
		<screen name="DetailInfoScreen" position="center,center" size="820,615" title="Package Info">
			<widget font="Regular;25" halign="center" name="pluginname" position="10,10" size="800,30" valign="center" zPosition="2"/>	
			<widget font="Regular;20" halign="left" name="author" position="10,60" size="800,25" valign="center" zPosition="2"/>	
			<widget font="Regular;20" halign="left" name="description" position="10,100" size="800,100" valign="top" zPosition="2"/>	
			<widget name="screenshot" position="250,250" size="300,330" alphatest="on"/>	
		</screen>
	
	"""

	def __init__(self, session, packageInfo):
		self.packageInfo = packageInfo
		Screen.__init__(self, session)

		self["actions"] = ActionMap(["WizardActions"], 
		{
			"back": self.close,
		})
		
		self["author"] = Label("")
		self["description"] = Label("")
		self["pluginname"] = Label("")
		self["screenshot"] = Pixmap()
		
		self.picload = ePicLoad()
		self.picload_conn = self.picload.PictureData.connect(self.paintScreenshotPixmapCB)
		
		self.onLayoutFinish.append(self.setInfos)
		
	def setInfos(self):
		if self.packageInfo[0].has_key("attributes"):
			self.attributes = self.packageInfo[0]["attributes"]
			#get the packagename
			if self.attributes.has_key("packagename"):
				self.title = self.attributes["packagename"]
				self.setTitle(_("Package Info: %s" %(self.title)))			
			#get the screenshot-url
			if self.attributes.has_key("screenshot"):
				self.loadThumbnail(self.attributes["screenshot"])
			#get the description
			if self.attributes.has_key("description"):
				self.description = _(self.attributes["description"].replace("\\n", "\n"))
			else:
				self.description = _("No description available")
			self["description"].setText(self.description)
			#get the author
			if self.attributes.has_key("author"):
				self.author = self.attributes["author"]
			else:
				self.author = _("unknown")	
			self["author"].setText(_("Author: ") + self.author)	
			#get the name
			if self.attributes.has_key("name"):
				self.pluginname = self.attributes["name"]
			else:
				self.pluginname = _("No name available")
			self["pluginname"].setText(self.pluginname)
			
	def loadThumbnail(self, url):
		if url is not None:
			self.thumbnail = "/tmp/" + url.split('/')[-1]
			if eNetworkManager.getInstance().online():
				client.downloadPage(url, self.thumbnail).addCallback(self.setThumbnail).addErrback(self.fetchFailed)
			else: 
				self.setThumbnail(noScreenshot = True)
		else:
			self.setThumbnail(noScreenshot = True)
			
	def setThumbnail(self, noScreenshot = False):
		if not noScreenshot:
			filename = self.thumbnail
		else:
			filename = None
		
		sc = AVSwitch().getFramebufferScale()
		self.picload.setPara((self["screenshot"].instance.size().width(), self["screenshot"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
		self.picload.startDecode(filename)

	def paintScreenshotPixmapCB(self, picInfo=None):
		ptr = self.picload.getData()
		if ptr != None:
			self["screenshot"].instance.setPixmap(ptr)
			self["screenshot"].show()
		else:
			self.setThumbnail(noScreenshot = True)
		
	def fetchFailed(self,string):
		self.setThumbnail(noScreenshot = True)
		print "[PluginDetails] fetch failed " + string.getErrorMessage()		
			
class AddonManagerConfigScreen(Screen, ConfigListScreen):
	skin = """
			<screen position="center,center" size="600,120" title="AddonManager - Config">
				<widget name="config" position="0,0" size="600,80" scrollbarMode="showOnDemand" />
				<widget name="ButtonGreentext" position="20,80" size="350,40" valign="center" halign="left" zPosition="10" font="Regular;18" transparent="1" />
				<widget name="ButtonGreen" pixmap="skin_default/buttons/button_green.png" position="0,90" zPosition="10" size="16,16" transparent="1" alphatest="on" />
			</screen>
		"""
        
	def __init__(self,session):
		self.session = session
		Screen.__init__(self, session)
		
		self["actions"] = ActionMap(["OkCancelActions","ColorActions"],
			{
				"cancel": self.close,
				"green": self.saveSelection,
			}, -1)
	
		self["ButtonGreen"] = Pixmap()
		self["ButtonGreentext"] = Label(_("Save settings"))
		
		self.list = []
		
		ConfigListScreen.__init__(self, self.list)
		
		self.createConfig()
		
	def saveSelection(self):
		for x in self["config"].list:
			x[1].save()
                        
		self.close()
		
	def createConfig(self, configElement=""):
		self.list = []
		self.list.append(getConfigListEntry(_("Use split screen layout:"), config.plugins.addonmanager.usesplitscreen))
		self["config"].setList(self.list)
	
class AddOnManagerLCDScreen(Screen):
	skin = (
	"""	<screen name="AddOnManagerLCDScreen" position="0,0" size="132,64" id="1">
			<widget name="plugin" position="4,0" size="132,30" font="Regular;14"/>
			<widget name="addon" position="4,30" size="132,30" font="Regular;12"/>
		</screen>""",
	"""	<screen name="AddOnManagerLCDScreen" position="0,0" size="96,64" id="2">
			<widget name="plugin" position="0,0" size="96,30" font="Regular;14"/>
			<widget name="addon" position="0,30" size="96,30" font="Regular;12"/>
		</screen>""",
	"""	<screen name="AddOnManagerLCDScreen" position="0,0" size="400,240" id="3">
			<widget name="plugin" position="0,0" size="400,50" font="Regular;40"/>
			<widget name="addon" foregroundColors="red,green,blue,yellow,white" position="0,50" size="400,120" font="Regular;50"/>
		</screen>"""
		 )
	
	def __init__(self,session,parent):
		Screen.__init__(self, session)
		self["plugin"] = Label(_("Merlin AddOn Browser"))
		self["addon"] = MultiColorLabel("")
		
	def setText(self, text, state=None):
		self["addon"].setText(text)
		if state is not None:
			self["addon"].setForegroundColorNum(state)
		else:
			self["addon"].setForegroundColorNum(4)
			
			
		
