import urllib2, xml.dom.minidom, os, zipfile, traceback, sys, xbmcgui, time
import cachedhttp

DEBUGMODE = 1


URL = 'http://www.xbmcscripts.com/scriptservice/scriptlist.php?view=all'

error = 'Error'
msg = 'Message'
popup = 'Popup'

#Debug data print function. Self explainary...
def printDebug(type, text):
    if DEBUGMODE == 1:
        if type == msg:
            print text
        elif type == error:
            print "\n" + "-"*5 + text + "-"*5
            traceback.print_exc(file=sys.stdout)
            print "-"*65 + "\n"
    if type == popup:
        xbmcgui.Dialog().ok('Error', text)
    else:
        return 
        
def node_string(node):
    result = ""
    for text in node.childNodes:
        result = result + text.nodeValue
    return result
    
def node_date(node):
    return time.strptime(node_string(node), '%Y-%m-%dT%H:%M:%S')

def node_int(node):
        return int(node_string(node))



#Settings class
#Much work to be done here. Should be able to change settings and so on in the future (when more settings are needed too)
class Settings:
    def __init__(self):
        #self.scriptpath = '../../scripts'
        self.scriptpath = 'Q:\\scripts\\'
        self.showfolder = 0
    def loadsettings(self):
        pass
    
    def w_scriptpath(self, path):
        pass
        

settings = Settings()

###XBMCSCRIPTS.COM INTERACTION###


class MyCachedHTTP(cachedhttp.CachedHTTP):

    def __init__(self, callback):
        self.callback = callback
        cachedhttp.CachedHTTP.__init__(self)
        
    
    def onDataRetrieved(self, bytesRead, totalSize, url, localfile):
        if (not (bytesRead is None))&(not (totalSize is None)):
                pct=int(bytesRead*100.0/totalSize)
                self.callback('dl', pct)
        return True # if you return false, then it means cancel the download
   
    def onDownloadFinished(self,success):
        self.callback('done', 100)


def download(link, callback):
    printDebug(msg, 'Downloading ' + str(link))
    fetcher = MyCachedHTTP(callback)
    fetcher.setUserAgent('xbmcscripts.com')
    data = fetcher.urlopen(link)
    data = urllib2.urlopen(link).read()
    return data
    
#Gets scriptlist and parses this (xml).
def getScriptlist_site(callback):
    printDebug(msg, "Fetching scriptlist from XBMCScripts.com")
    try:
        data = urllib2.urlopen(URL).read()
        if data != None or data > 50:
            printDebug(msg, "Scriptlist downloaded successfully!")
        else:
            printDebug(popup, "Couldn't fetch scriptlist, returned empty object")
    except:
        printDebug(error, "Error while fetching scriptlist:")
        pass
        
    printDebug(msg, "Parsing XML in scriptlist data")
    try:
        from xml.dom.minidom import parseString
        doc = parseString(data)
        printDebug(msg, "Parsing done successfully!")
        return doc
    except:
        printDebug(error, "Parsing failed:")
        pass

#Local scriptlist function. Gets all folders in the local scripts directory, checks for an xml file, if found it parses this and passes on info, if not only name is passed on.
#See ParseXML.parselocal() for the real code taking care of the parsing.

def getScriptlist_local():
    printDebug(msg, "Fetching local scriptlist")
    try:
        os.chdir(settings.scriptpath)
        scripts = []
        dir = os.listdir(settings.scriptpath)
        del dir[dir.index('XBMCScripts')]
        import glob
        for x in dir:
            if glob.glob(settings.scriptpath + "\\" + x + "\\*.py"):
                scripts.append(x)
                
        if DEBUGMODE == 1:
            for x in scripts:
                print x
        printDebug(msg, "Local script dir accessed successfully")
        return scripts
    except:
        printDebug(error, "Error while accessing local script directory")
        return None

        
class ParseXML:
    #Function for parsing the data got from site. Shouldn't need work really...
    def parsesite(self, callback):
        doc = getScriptlist_site(callback)
        if doc != None:
            scriptlist = []
            scripts = doc.firstChild.childNodes
            for script in scripts:
                if script.nodeType != xml.dom.minidom.Node.ELEMENT_NODE: continue
                script_temp = {}
                description = category = id = date = downloads = "Unknown"
                for property in script.childNodes:
                    if property.nodeType != xml.dom.minidom.Node.ELEMENT_NODE: continue
                    name = property.nodeName
                    if name == "date":
                        value = node_date(property)
                    elif name == "downloads": value = node_int(property)
                    else: value = node_string(property)
                    script_temp[name] = value
                scriptlist.append(script_temp)
            return scriptlist
    #Parses the xml files found in local scripts directories. Follows and outdated script spec, but should be able to be updated without too much hassle.
    #Returns a dictionary with script info.
    def parselocal(self):
        list = getScriptlist_local()
        scriptlist = []
        if list != None:
            for item in list:
                if os.path.isfile(item + '/script.xml') == 1:
                    print "xml found!"
                    xmldesc = open(item + '/script.xml', 'r').read()
                    from xml.dom.minidom import parseString
                    doc = parseString(xmldesc)
                
                    print doc
                    name = None
                    author = version = updated = desc = changelog = firstrun = "Unknown"
                    scripts = doc.childNodes
                    script_temp = {}
                    for script in scripts:
                        if script.nodeType != xml.dom.minidom.Node.ELEMENT_NODE: continue
                        for property in script.childNodes:
                            script_temp[property.nodeName] = node_string(property)
                            
                    scriptlist.append(script_temp)
                else:
                    print "no script.xml found"
                    script_temp = {}
                    script_temp["name"] = item
                    script_temp["author"] = script_temp["version"] = script_temp["updated"] = script_temp["desc"] = script_temp["changelog"] = script_temp["firstrun"] = "Unknown"
                    scriptlist.append(script_temp)
            if scriptlist != []:
                return scriptlist
            else:
                printDebug(msg, "XML not well-formed or unknown tags")



def unzip(path, filename): #Unzips files to path
        try:
            zip = zipfile.ZipFile(filename, 'r')
            namelist = zip.namelist()
            if os.path.exists(settings.scriptpath + namelist[0]):
                if xbmcgui.Dialog().yesno('Overwrite?', 'Folder ' + namelist[0][0:-1] + 'already exists.', 'Overwrite files inside folder?') != True:
                    return False, None
            isdir = os.path.isdir 
            join = os.path.join 
            norm = os.path.normpath 
            split = os.path.split
            dirlist = []
            for item in namelist:
                if not item.endswith('/'): 
                    root, name = split(item) 
                    directory = norm(join(path, root)) 
                    if not isdir(directory): 
                        os.makedirs(directory) 
                    file(join(directory, name), 'wb').write(zip.read(item)) 
            zip.close()
            del zip
            #namelist[0][0:-1] returns the name of the folder the script was installed into (root folder in zip).
            return True, namelist[0][0:-1]
        except:
            printDebug(popup, "An error occoured while unzipping.\nCorrupt file or not a zip file.")
            printDebug(error, "An error occoured while unzipping: ")
            return False, None


def install(url, callback, scriptinfo):
        
        data = download(url, callback)
        if data != None:
            f = open(settings.scriptpath + 'temp.zip', 'wbo')
            f.write(data)
            f.close()
            state = unzip(settings.scriptpath , settings.scriptpath + 'temp.zip')
            if settings.showfolder == 1 and state[0] == True:
                xbmcgui.Dialog().ok('Install done', 'Script installed successfully into folder ' + str(state[1]))
            return state[0]
        else:
            print "DATA = NONE"
            return false
