import xbmc
import xbmcgui
import xbmcplugin
import common
import re
import sys
import binascii
import struct
from Crypto.Cipher import AES
from Crypto.Hash import MD5
from BeautifulSoup import BeautifulSoup, BeautifulStoneSoup

class Main:

    def __init__( self ):
        #select from avaliable streams, then play the file
        self.play()        
    
    def decrypt_id(self, p):
        cp_strings = [
            '6fe8131ca9b01ba011e9b0f5bc08c1c9ebaf65f039e1592d53a30def7fced26c',
            'd3802c10649503a60619b709d1278ffff84c1856dfd4097541d55c6740442d8b',
            'c402fb2f70c89a0df112c5e38583f9202a96c6de3fa1aa3da6849bb317a983b3',
            'e1a28374f5562768c061f22394a556a75860f132432415d67768e0c112c31495',
            'd3802c10649503a60619b709d1278efef84c1856dfd4097541d55c6740442d8b'
        ]

        v3 = p.split("~")
        v3a = binascii.unhexlify(v3[0])
        v3b = binascii.unhexlify(v3[1])

        ecb = AES.new(v3b, AES.MODE_ECB)
        tmp = ecb.decrypt(v3a)

        for v1 in cp_strings[:]:
            ecb = AES.new(binascii.unhexlify(v1), AES.MODE_ECB)
            v2 = ecb.decrypt(tmp)
            if (re.match("[0-9A-Za-z_-]{32}", v2)):
                return v2

    def decrypt_SMIL(self, encsmil):
        encdata = binascii.unhexlify(encsmil)

        xmldeckeys = [
            ['B7F67F4B985240FAB70FF1911FCBB48170F2C86645C0491F9B45DACFC188113F',
             'uBFEvpZ00HobdcEo'],
            ['3484509D6B0B4816A6CFACB117A7F3C842268DF89FCC414F821B291B84B0CA71',
             'SUxSFjNUavzKIWSh'],
            ['1F0FF021B7A04B96B4AB84CCFD7480DFA7A972C120554A25970F49B6BADD2F4F',
             'tqo8cxuvpqc7irjw'],
            ['76A9FDA209D4C9DCDFDDD909623D1937F665D0270F4D3F5CA81AD2731996792F',
             'd9af949851afde8c'],
            ['852AEA267B737642F4AE37F5ADDF7BD93921B65FE0209E47217987468602F337',
             'qZRiIfTjIGi3MuJA'],
            ['8CE8829F908C2DFAB8B3407A551CB58EBC19B07F535651A37EBC30DEC33F76A2',
            'O3r9EAcyEeWlm5yV'],
            ['246DB3463FC56FDBAD60148057CB9055A647C13C02C64A5ED4A68F81AE991BF5',
             'vyf8PvpfXZPjc7B1'],
            ['4878B22E76379B55C962B18DDBC188D82299F8F52E3E698D0FAF29A40ED64B21',
             'WA7hap7AGUkevuth']
        ]

        for key in xmldeckeys[:]:
            smil=""
            out=[0,0,0,0]
            ecb = AES.new(binascii.unhexlify(key[0]), AES.MODE_ECB)
            unaes = ecb.decrypt(encdata)

            packer = struct.Struct("iiii")
            xorkey = packer.unpack(key[1])

            for i in range(0, len(encdata)/16):
                x = unaes[i*16:i*16+16]
                res = packer.unpack(x)
                for j in range(0,4):
                    out[j] = res[j] ^ xorkey[j]
                x = encdata[i*16:i*16+16]
                xorkey = packer.unpack(x)
                x = packer.pack(out[0],out[1],out[2],out[3])
                smil = smil + x

            if (smil.find("<smil") == 0):
                i = smil.rfind("</smil>")
                smil = smil[0:i+7]
                return smil

    def play( self ):
        #getCID
        print common.args.url
        html=common.getHTML(common.args.url)
        if common.args.mode == 'HD_play':
            p=re.compile('swfObject.addVariable\("content_id", ([0-9]*)\);')
        else:
            p=re.compile('UserHistory.add_watched_history\((.+?)\)')
        cid=p.findall(html)[0]
        cid="http://r.hulu.com/videos?content_id="+cid
        #getPID
        html=common.getHTML(cid)
        cidSoup=BeautifulStoneSoup(html)
        pid=cidSoup.findAll('pid')[0].contents[0]        
        pid=self.decrypt_id(pid)
        m=MD5.new()
        m.update(str(pid) + "yumUsWUfrAPraRaNe2ru2exAXEfaP6Nugubepreb68REt7daS79fase9haqar9sa")
        auth=m.hexdigest()
        print auth

        #getSMIL
        #smilURL = "http://releasegeo.hulu.com/content.select?pid=" + hulu_decrypt_id(pid) + "&mbr=true&format=smil"
        smilURL = "http://s.hulu.com/select.ashx?pid=" + pid + "&auth=" + auth + "&v=810006400"
        print 'HULU --> SMILURL: ' + smilURL
        smilXML=common.getHTML(smilURL)
        tmp=self.decrypt_SMIL(smilXML)
        smilSoup=BeautifulStoneSoup(tmp)
        print smilSoup.prettify()
        #getRTMP
        video=smilSoup.findAll('video')
        streams=[]
        selectedStream = None
        qtypes=['ask', 'H264 Medium', 'H264 650K', 'H264 400K',
            'High', 'Medium', 'Low']
        
        #label streams
        qt = int(common.settings['quality'])
        if qt < 0 or qt > 6: qt = 0

        while qt < 6:
            qtext = qtypes[qt]

            for vid in video:
                if qt == 0:
                    streams.append([vid['profile'],vid['src']])
                if qt > 3 and 'H264' in vid['profile']: continue
                if qtext in vid['profile']:
                    selectedStream = vid['src']
                    break

            if qt == 0 or selectedStream != None: break
            qt += 1

        if qt == 0 or selectedStream == None:
            #ask user for quality level
            quality=xbmcgui.Dialog().select('Please select a quality level:', [stream[0] for stream in streams])
            print quality
            if quality!=-1:
                selectedStream = streams[quality][1]
                print "stream url"
                print selectedStream
        if selectedStream != None:
            #form proper streaming url
            rawurl=selectedStream.replace('&amp;','&').replace('&lt;','<').replace('&gt;','>')
            mainParts = rawurl.split("?")
            queryStringParts = mainParts[1].split("&")
            v9 = queryStringParts[0]
            v6 = queryStringParts[1]
            
            if "<break>" in queryStringParts[2]:
                breakParts = queryStringParts[2].split("<break>")
                v3 = breakParts[0];
                fileName = breakParts[1]
            else:
                v3 = queryStringParts[2]
                breakFilenameURL = mainParts[0].split("://");
                breakFilenamedir = breakFilenameURL[1].split("/");
                breakFilenames = breakFilenameURL[1].split(breakFilenamedir[1] + "/")
                fileName = breakFilenames[1]
                
            newQueryString = v9 + "&" + v6 + "&" + v3
            
            protocolSplit = rawurl.split("://")
            pathSplit = protocolSplit[1].split("/");
            serverPath = pathSplit[0] + "/" + pathSplit[1];

            server = pathSplit[0];
            appName = pathSplit[1];

            videoIdentIp = server
            
            protocol = "rtmpe";
            port = "1935";
            newUrl =  protocol + "://" + videoIdentIp + ":" + port + "/" + appName + "?_fcs_vhost=" + server

            if newQueryString <> "":
                    newUrl += "&" + newQueryString

     
            print "item url -- > " + newUrl
            print "playPath -- > " + fileName
            if common.args.mode == 'HD_play':
                SWFPlayer = 'http://www.hulu.com/playerHD.swf'
            else:
                SWFPlayer = 'http://www.hulu.com/player.swf'

        #define item
            item = xbmcgui.ListItem(common.args.name)
            item.setProperty("SWFPlayer", SWFPlayer)
            item.setProperty("PlayPath", fileName)
            item.setProperty("PageURL", common.args.url)

            if common.settings['resolution_hack']:
                ok=xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=newUrl,listitem=item)
                xbmcplugin.endOfDirectory( handle=int( sys.argv[ 1 ] ), updateListing=False,  succeeded=ok)
            else:    
                playlist = xbmc.PlayList(1)
                playlist.clear()
                playlist.add(newUrl, item)
                play=xbmc.Player().play(playlist)
                xbmc.executebuiltin('XBMC.ActivateWindow(fullscreenvideo)')
            
            
