import xbmc, xbmcgui
import os, re, sqlite3
from BeautifulSoup import BeautifulStoneSoup
from xbe import XBE

pDialog = xbmcgui.DialogProgress()

BASE_DIR_EMULATORS 	= ['E:\\Emulators', 'E:\\Emus', 'F:\\Emulators', 'F:\\Emus', 'G:\\Emulators', 'G:\\Emus']
MYPROGRAMS_DB = xbmc.translatePath('special://profile/database/MyPrograms6.db')

ACTION_PARENT_DIR2 	= 92 # ACTION_NAV_BACK
ACTION_CLOSE 		= 10 # ACTION_PREVIOUS_MENU
ACTION_SELECT		= 7 # ACTION_SELECT_ITEM

_SHORTCUT_ID = sys.argv[1:][0]

class CGUIShortcuts( xbmcgui.WindowXMLDialog ):
		
	def __init__( self, *args, **kwargs ):
		self.category 	= 'menu'
		self.type	 	= 'root'
		self.content 	= 'root'
		self.root = True
		
	def onInit(self):
		self.set_controls()
		self.add_menu(root=True)
	
	def onFocus(self, controlId):
		pass
	
	def onAction( self, action ):
		this = 'onAction-> {}'
		
		if action == ACTION_CLOSE:
			self.close()
		if action == ACTION_PARENT_DIR2:
			self.add_menu(root=True)
			if self.root:
				self.close()
			self.root = True
			
	def onClick( self, controlId ):
		this = 'onClick-> {}'
		
		if controlId == 6:
			self.root = False
			
			item = self.getControl(6).getSelectedItem()
			
			category = item.getProperty('category')
			type 	 = item.getProperty('type')
			
			if item.getLabel() == '...':
				self.root = True
				self.add_menu()
			elif category == 'menu':
				self.add_menu(root=False)
			elif category in ('plugins','scripts','emulators'):
				self.fetch_addons(category, type)
			elif category == 'applications':
				self.get_apps()
			elif category == 'games':
				self.get_games()
			elif category == 'homebrew':
				self.get_homebrew()
			elif category == 'clear':
				self.clear_title()
			elif category == 'browse':
				self.browse_items()
			elif category == 'item':
				self.set_shortcut(item)
		
	def set_controls( self ):
		this = 'set_controls-> {}'
		self.getControl(1).setLabel( 'Select Shortcut %s' % _SHORTCUT_ID )
		self.getControl(3).setVisible(False)
		self.getControl(5).setVisible(False)
		self.getControl(6).setVisible(True)
		self.setFocus( self.getControl(6) )
		
	def add_menu( self, root=True ):
		this = 'add_menu-> {}'
		
		self.getControl(6).reset()
		
		if root:
			items = [	( 'Browse Files', '', 'defaultFolder.png', 'browse', '' ), 
						( 'Applications', '', 'defaultFolder.png', 'applications', '' ),
						( 'Emulators', '', 'defaultFolder.png', 'emulators', '' ),
						( 'Games', '', 'defaultFolder.png', 'games', '' ),
						( 'Homebrew', '', 'defaultFolder.png', 'homebrew', '' ),
						( 'Scripts', '', 'defaultFolder.png', 'scripts', '' )
					]
		
			if xbmc.getCondVisibility("Skin.HasSetting(Skin.Shortcut.{}.Enabled)".format(_SHORTCUT_ID)):
				items.insert(0, ("Clear", "", "defaultFolder.png", "clear", ""))
		
		for label, label2, icon, category, type  in items:
			listItem = xbmcgui.ListItem( label, label2, icon )
			listItem.setProperty( 'category', category )
			listItem.setProperty( 'type', type )
			self.getControl(6).addItem(listItem)
			
		self.setFocus( self.getControl(6) )
	
	def fetch_addons(self, category, type):
		this = 'fetch_addons-> {}'

		base_paths = self.build_path(category, type)
		if not base_paths:
			return

		self.getControl(6).reset()
		listItem = xbmcgui.ListItem('...', '', 'defaultFolderBack.png')
		self.getControl(6).addItem(listItem)

		for base_path in base_paths:
			if not os.path.isdir(base_path):
				continue
			
			directories = os.listdir(base_path)

			for directory in directories:
				addon_path = os.path.join(base_path, directory)
				addon_xml = os.path.join(addon_path, 'addon.xml')

				if os.path.isfile(addon_xml):
					addon_func = self.build_func(category, type, addon_path)
					self.add_item(self.get_addon(addon_xml), addon_path, addon_func)

	def build_path(self, category, type):
		this = 'build_path-> {}'

		if category == 'plugins':
			return [xbmc.translatePath('special://home/plugins/{}/'.format(type))]
		elif category == 'scripts':
			return [xbmc.translatePath('special://scripts/XBMC4Gamers Extras/'), xbmc.translatePath('special://scripts/')]
		elif category == 'emulators':
			return BASE_DIR_EMULATORS
		else:
			return None
			
	def add_item( self, addon, addon_path, addon_func ):
		this = 'add_item-> {}'
		try:
			icon = self.get_icon(addon_path)
			meta = addon.find( 'extension', {'point':'xbmc.addon.metadata'} )
			
			listItem = xbmcgui.ListItem( addon['name'], addon['version'], icon )
			
			listItem.setProperty( 'Addon.ID', 			addon['id'] )
			listItem.setProperty( 'Addon.Name', 		addon['name'] )
			listItem.setProperty( 'Addon.Version', 		addon['version'] )
			listItem.setProperty( 'Addon.Creator', 		addon['provider-name'] )
			listItem.setProperty( 'Addon.Icon', 		icon )
			listItem.setProperty( 'Addon.Summary', 		str(meta.summary.string) )
			listItem.setProperty( 'Addon.FolderName', 	os.path.dirname(addon_path) )
			listItem.setProperty( 'Addon.Description', 	str(meta.description.string) )
			
			listItem.setProperty( 'path', 				addon_func )
			listItem.setProperty( 'category', 			'item' )
			
			self.getControl(6).addItem(listItem)
		except:
			pass
		
	def get_addon( self, addon_xml ):
		this = 'get_addon-> {}'
		
		data_raw	= open( addon_xml, 'r' ).read()
		data		= BeautifulStoneSoup(data_raw).find('addon')
		return data

	def get_apps( self ):		
		self.getControl(6).reset()
		listItems = []
		listItem = xbmcgui.ListItem( '...', '', 'defaultFolderBack.png' )
		listItems.append(listItem)
		
		with sqlite3.connect(MYPROGRAMS_DB) as con:
			con.text_factory = str
			cur = con.cursor()
			applicationsSQL = 'SELECT xbeDescription, Synopsis, altname, strFileName FROM files WHERE lower(strFileName) LIKE "%:\\applications%" OR lower(strFileName) LIKE "%:\\apps%" ORDER BY xbeDescription;'
			cur.execute(applicationsSQL)
			rows = cur.fetchall()

		apps = [(row[0].title(), row[1], row[2], row[3]) for row in rows]
		total_apps = len(apps)
		
		if total_apps >= 50:
			pDialog.create('Generating List')
		for index, (title, synopsis, altname, path) in enumerate(apps, start=0):
			if not altname:
				altname = title
			root_path = os.path.dirname(path)
			thumb_list = os.path.join(root_path, '_resources\\artwork\\poster_small.jpg')
			thumb = os.path.join(root_path, '_resources\\artwork\\poster.jpg')
			if str(_SHORTCUT_ID) in ['1', '2', '3', '4', '5']:
				thumb = os.path.join(root_path, '_resources\\artwork\\synopsis.jpg')
			
			# print "Title: {} | Path: {}".format(title, path)
			
			listItem = xbmcgui.ListItem(altname, root_path, thumb, thumb_list)
			if str(_SHORTCUT_ID) in ['1', '2', '3', '4', '5']:
				listItem.setProperty("overview", synopsis)
			else:
				listItem.setProperty("overview", "")
			listItem.setProperty("path", path)
			listItem.setProperty("Addon.Icon", thumb)
			listItem.setProperty('category', 'item')
			
			progress = int((index * 100) / total_apps)
			if index % 20 == 0:
				pDialog.update(progress, "", "Scanning Applications[CR]Please wait...")
			
			listItems.append(listItem)
			
		pDialog.close()
		listItems = sorted(listItems, key=lambda item: item.getLabel())
		self.getControl(6).addItems(listItems)

	def get_games( self ):		
		self.getControl(6).reset()
		listItems = []
		listItem = xbmcgui.ListItem( '...', '', 'defaultFolderBack.png' )
		listItems.append(listItem)

		with sqlite3.connect(MYPROGRAMS_DB) as con:
			con.text_factory = str
			cur = con.cursor()
			gamesSQL = 'SELECT xbeDescription, Synopsis, altname, strFileName FROM files WHERE lower(strFileName) LIKE "%:\\games%" ORDER BY xbeDescription;'
			cur.execute(gamesSQL)
			rows = cur.fetchall()
			
		games = [(row[0].title(), row[1], row[2], row[3]) for row in rows]
		total_games = len(games)
		
		if total_games >= 50:
			pDialog.create('Generating List')
		for index, (title, synopsis, altname, path) in enumerate(games, start=0):
			if not altname:
				altname = title
			root_path = os.path.dirname(path)
			thumb_list = os.path.join(root_path, '_resources\\artwork\\poster_small.jpg')
			thumb = os.path.join(root_path, '_resources\\artwork\\poster.jpg')
			if str(_SHORTCUT_ID) in ['1', '2', '3', '4', '5']:
				thumb = os.path.join(root_path, '_resources\\artwork\\synopsis.jpg')
			
			# print "Title: {} | Path: {}".format(title, path)
			
			listItem = xbmcgui.ListItem(altname, root_path, thumb, thumb_list)
			listItem.setProperty("overview", synopsis)
			listItem.setProperty("path", path)
			listItem.setProperty("Addon.Icon", thumb)
			listItem.setProperty('category', 'item')
			
			progress = int((index * 100) / total_games)
			if index % 60 == 0:
				pDialog.update(progress, "", "Scanning Games[CR]Please wait...")
			
			listItems.append(listItem)
			
		pDialog.close()
		listItems = sorted(listItems, key=lambda item: item.getLabel())
		self.getControl(6).addItems(listItems)

	def get_homebrew( self ):
		self.getControl(6).reset()
		listItems = []
		listItem = xbmcgui.ListItem( '...', '', 'defaultFolderBack.png' )
		listItems.append(listItem)

		with sqlite3.connect(MYPROGRAMS_DB) as con:
			con.text_factory = str
			cur = con.cursor()
			homebrewSQL = 'SELECT xbeDescription, Synopsis, altname, strFileName FROM files WHERE lower(strFileName) LIKE "%:\\homebrew%" OR lower(strFileName) LIKE "%:\\ports%" ORDER BY xbeDescription;'
			cur.execute(homebrewSQL)
			rows = cur.fetchall()
			
		homebrew = [(row[0].title(), row[1], row[2], row[3]) for row in rows]
		total_homebrew = len(homebrew)
		
		if total_homebrew >= 50:
			pDialog.create('Generating List')
		for index, (title, synopsis, altname, path) in enumerate(homebrew, start=0):
			if not altname:
				altname = title
			root_path = os.path.dirname(path)
			thumb_list = os.path.join(root_path, '_resources\\artwork\\poster_small.jpg')
			thumb = os.path.join(root_path, '_resources\\artwork\\poster.jpg')
			if str(_SHORTCUT_ID) in ['1', '2', '3', '4', '5']:
				thumb = os.path.join(root_path, '_resources\\artwork\\synopsis.jpg')
			
			# print "Title: {} | Path: {}".format(title, path)
			
			listItem = xbmcgui.ListItem(altname, root_path, thumb, thumb_list)
			listItem.setProperty("overview", synopsis)
			listItem.setProperty("path", path)
			listItem.setProperty("Addon.Icon", thumb)
			listItem.setProperty('category', 'item')
			
			progress = int((index * 100) / total_homebrew)
			if index % 20 == 0:
				pDialog.update(progress, "", "Scanning Homebrew[CR]Please wait...")
			
			listItems.append(listItem)
			
		pDialog.close()
		listItems = sorted(listItems, key=lambda item: item.getLabel())
		self.getControl(6).addItems(listItems)

	def browse_items(self):
		Dialog = xbmcgui.Dialog()
		search_path = Dialog.browse(1, "Select a .xbe or .py file", "files", ".xbe|.py")
		
		if search_path == -1:
			return None

		path = search_path
		thumb = ""
		synopsis = ""
		category = "emulators"

		if search_path.endswith(".xbe"):
			title = XBE(path).Get_title()

			with sqlite3.connect(MYPROGRAMS_DB) as con:
				con.text_factory = str
				cur = con.cursor()
				gamesSQL = "SELECT xbeDescription, Synopsis, strFileName FROM files WHERE lower(strFileName) LIKE ? ORDER BY xbeDescription;"
				cur.execute(gamesSQL, (path.lower(),))
				row = cur.fetchone()

			if row:
				title, synopsis, path = row
				root_path = os.path.dirname(path)
		else:
			title = os.path.basename(os.path.dirname(path))
			if not title:
				title = os.path.basename(path.replace(".py", ""))
			thumb = self.get_icon(os.path.dirname(path))
			category = "script"

		listItem = xbmcgui.ListItem(title, title, thumb, thumb)
		listItem.setProperty("overview", synopsis)
		listItem.setProperty("path", path)
		listItem.setProperty("Addon.Icon", thumb)
		listItem.setProperty("category", category)

		if listItem:
			self.set_shortcut(listItem)
		else:
			pass
		
	def clear_title( self ):
		xbmc.executebuiltin( 'Skin.Reset(Skin.Shortcut.{}.Title)'.format(_SHORTCUT_ID) )
		xbmc.executebuiltin( 'Skin.Reset(Skin.Shortcut.{}.Icon)'.format(_SHORTCUT_ID) )
		xbmc.executebuiltin( 'Skin.Reset(Skin.Shortcut.{}.Path)'.format(_SHORTCUT_ID) )
		xbmc.executebuiltin( 'Skin.Reset(Skin.Shortcut.{}.Overview)'.format(_SHORTCUT_ID) )
		xbmc.executebuiltin( 'Skin.Reset(Skin.Shortcut.{}.Enabled)'.format(_SHORTCUT_ID) )
		xbmc.executebuiltin( 'Xbmc.Notification(XBMC Shortcut, Shortcut {} has been cleared!)'.format(_SHORTCUT_ID) )
		self.close()

	def build_func( self, category, type, directory):
		this = 'build_func-> {}'
		if category == 'scripts':
			func = '{}\\default.py'.format(directory)
		elif category == 'emulators':
			func = '{}\\default.xbe'.format(directory)
		return func
		
	def get_icon(self, path):
		addon_path = os.path.join(path, "addon.png")
		default_tbn = os.path.join(path, "default.tbn")
		icon_png = os.path.join(path, "icon.png")
		default_folder = os.path.join(path, "defaultFolder.png")

		if os.path.isfile(addon_path):
			return addon_path
		elif os.path.isfile(default_tbn):
			return default_tbn
		elif os.path.isfile(icon_png):
			return icon_png
		else:
			return default_folder
	
	def set_shortcut(self, listItem):
		this = 'set_shortcut-> '
		
		xbe_path = listItem.getProperty('Path')
		default_icon = "defaultshortcutmissing.png"

		if xbe_path:
			thumb_cache = xbmc.getCacheThumbName(xbe_path)
			thumb_path = "special://profile/Thumbnails/Programs/{}/{}".format(thumb_cache[0], thumb_cache)
			tbn_file = os.path.join(os.path.dirname(xbe_path), 'default.tbn')

			addon_icon = os.path.join(os.path.dirname(xbe_path), "addon.png")
			icon_path = listItem.getProperty('Addon.Icon')
			if os.path.isfile(addon_icon):
				icon_path = addon_icon
			elif not os.path.isfile(icon_path):
				icon_path = thumb_path if os.path.isfile(thumb_path) else default_icon

				if os.path.isfile(tbn_file):
					xbmc.executebuiltin('CacheThumbnail("{}","{}")'.format(tbn_file, thumb_path))
					if os.path.isfile(thumb_path):
						icon_path = thumb_path

			listItem.setProperty('Addon.Icon', icon_path)

			xbmc.executebuiltin('Skin.SetString(Skin.Shortcut.{}.Title,{})'.format(_SHORTCUT_ID, listItem.getLabel()))
			xbmc.executebuiltin('Skin.SetString(Skin.Shortcut.{}.Icon,{})'.format(_SHORTCUT_ID, icon_path))
			xbmc.executebuiltin('Skin.SetString(Skin.Shortcut.{}.Path,{})'.format(_SHORTCUT_ID, listItem.getProperty('Path')))
			xbmc.executebuiltin('Skin.SetString(Skin.Shortcut.{}.Overview,{})'.format(_SHORTCUT_ID, listItem.getProperty('Overview')))
			xbmc.executebuiltin('Skin.SetBool(Skin.Shortcut.{}.Enabled,{})'.format(_SHORTCUT_ID, 'True'))
			xbmc.executebuiltin('Xbmc.Notification(XBMC Shortcut, Shortcut {} has been set!)'.format(_SHORTCUT_ID))

		self.close()
				
if __name__ == '__main__':
	xbmc.executebuiltin( 'Skin.SetBool(DialogSelectListItem6)' )
	win = CGUIShortcuts( 'DialogSelect.xml', os.getcwd() )
	win.doModal()
	del win