"""
Update module

Nuka1195
"""

# main imports
import sys
import os
import xbmc
import xbmcgui
import xbmcplugin

import urllib
import re
from xml.sax.saxutils import unescape


class Parser:
    """ Parser Class: grabs all tag versions and urls """
    # regexpressions
    revision_regex = re.compile( '<h2>Revision ([0-9]*): ([^<]*)</h2>' )
    asset_regex = re.compile( '<li><a href="([^"]*)">([^"]*)</a></li>' )

    def __init__( self, htmlSource ):
        # set our initial status
        self.dict = { "status": "fail", "revision": 0, "assets": [], "url": "" }
        # fetch revision number
        self._fetch_revision( htmlSource )
        # if we were successful, fetch assets
        if ( self.dict[ "revision" ] != 0 ):
            self._fetch_assets( htmlSource )

    def _fetch_revision( self, htmlSource ):
        try:
            # parse revision and current dir level
            revision, url = self.revision_regex.findall( htmlSource )[ 0 ]
            # we succeeded :), set our info
            self.dict[ "url" ] = url
            self.dict[ "revision" ] = int( revision )
        except:
            pass

    def _fetch_assets( self, htmlSource ):
        try:
            assets = self.asset_regex.findall( htmlSource )
            if ( len( assets ) ):
                for asset in assets:
                    if ( asset[ 0 ] != "../" ):
                        self.dict[ "assets" ] += [ unescape( asset[ 0 ] ) ]
                self.dict[ "status" ] = "ok"
        except:
            pass


class _Info:
    def __init__( self, *args, **kwargs ):
        self.__dict__.update( kwargs )


class Main:
    def __init__( self ):
        self.dialog = xbmcgui.DialogProgress()
        # get the repository info
        self._get_repo_info()
        # parse sys.argv for our current url
        self._parse_argv()
        # create the script/plugin/skin title
        self.title = self.args.download_url.split( "/" )[ -2 ].replace( "%20", " " )
        # get the list
        self._download_item()

    def _get_repo_info( self ):
        # path to info file
        repopath = os.path.join( os.getcwd(), "resources", "repositories", xbmcplugin.getSetting( "repository" ), "repo.xml" )
        try:
            # grab a file object
            fileobject = open( repopath, "r" )
            # read the info
            info = fileobject.read()
            # close the file object
            fileobject.close()
            # repo's base url
            self.REPO_URL = re.findall( '<url>([^<]+)</url>', info )[ 0 ]
        except:
            # oops print error message
            print "ERROR: %s::%s (%d) - %s" % ( self.__class__.__name__, sys.exc_info()[ 2 ].tb_frame.f_code.co_name, sys.exc_info()[ 2 ].tb_lineno, sys.exc_info()[ 1 ], )

    def _parse_argv( self ):
        # call _Info() with our formatted argv to create the self.args object
        exec "self.args = _Info(%s)" % ( sys.argv[ 2 ][ 1 : ].replace( "&", ", " ).replace( "\\u0027", "'" ).replace( "\\u0022", '"' ).replace( "\\u0026", "&" ), )
        self.args.download_url = urllib.unquote_plus( self.args.download_url )

    def _download_item( self ):
        try:
            if ( xbmcgui.Dialog().yesno( self.title, xbmc.getLocalizedString( 30000 ), "", "", xbmc.getLocalizedString( 30020 ), xbmc.getLocalizedString( 30021 ) ) ):
                self.dialog.create( self.title, xbmc.getLocalizedString( 30002 ), xbmc.getLocalizedString( 30003 ) )
                asset_files = []
                folders = [ self.args.download_url ]
                while folders:
                    try:
                        htmlsource = self._get_html_source( self.REPO_URL + folders[ 0 ] )
                        if ( not htmlsource ): raise
                        items = self._parse_html_source( htmlsource )
                        if ( not items or items[ "status" ] == "fail" ): raise
                        files, dirs = self._parse_items( items )
                        for file in files:
                            asset_files.append( "%s/%s" % ( items[ "url" ], file, ) )
                        for folder in dirs:
                            folders.append( folders[ 0 ] + folder )
                        folders = folders[ 1 : ]
                    except:
                        folders = []
                self._get_files( asset_files )
        except:
            # oops print error message
            print "ERROR: %s::%s (%d) - %s" % ( self.__class__.__name__, sys.exc_info()[ 2 ].tb_frame.f_code.co_name, sys.exc_info()[ 2 ].tb_lineno, sys.exc_info()[ 1 ], )
            self.dialog.close()
            xbmcgui.Dialog().ok( self.title, xbmc.getLocalizedString( 30030 ) )
        
    def _get_files( self, asset_files ):
        """ fetch the files """
        try:
            finished_path = ""
            for cnt, url in enumerate( asset_files ):
                items = os.path.split( url )
                # TODO: Change this to U: for other than xbox
                drive = xbmc.translatePath( ( "U:\\%s" % self.args.install, "Q:\\%s" % self.args.install, )[ os.environ.get( "OS", "xbox" ) == "xbox" ] )
                path = os.path.join( drive, os.path.sep.join( items[ 0 ].split( "/" )[ self.args.ioffset : ] ).replace( "%20", " " ) )
                if ( not finished_path ): finished_path = path
                file = items[ 1 ].replace( "%20", " " )
                pct = int( ( float( cnt ) / len( asset_files ) ) * 100 )
                self.dialog.update( pct, "%s %s" % ( xbmc.getLocalizedString( 30005 ), url, ), "%s %s" % ( xbmc.getLocalizedString( 30006 ), path, ), "%s %s" % ( xbmc.getLocalizedString( 30007 ), file, ) )
                if ( self.dialog.iscanceled() ): raise
                if ( not os.path.isdir( path ) ): os.makedirs( path )
                url = self.REPO_URL + url
                fpath = os.path.join( path, file )
                urllib.urlretrieve( url.replace( " ", "%20" ), fpath )
        except:
            # oops print error message
            print "ERROR: %s::%s (%d) - %s" % ( self.__class__.__name__, sys.exc_info()[ 2 ].tb_frame.f_code.co_name, sys.exc_info()[ 2 ].tb_lineno, sys.exc_info()[ 1 ], )
            raise
        else:
            self.dialog.close()
            xbmcgui.Dialog().ok( self.title, xbmc.getLocalizedString( 30008 ), finished_path )
            
    def _get_html_source( self, url ):
        try:
            sock = urllib.urlopen( url )
            htmlsource = sock.read()
            sock.close()
            return htmlsource
        except:
            return ""

    def _parse_html_source( self, htmlsource ):
        """ parse html source for tagged version and url """
        try:
            parser = Parser( htmlsource )
            #parser.feed( htmlsource )
            #parser.close()
            return parser.dict
        except:
            return {}
            
    def _parse_items( self, items ):
        """ separates files and folders """
        folders = []
        files = []
        for item in items[ "assets" ]:
            if ( item.endswith( "/" ) ):
                folders.append( item )
            else:
                files.append( item )
        return files, folders
