__author__ = "suxoza <suxoza@gmail.com>"

from urlparse import parse_qs
from urllib2 import urlopen
import re,sys,json,pprint




def saxli(ID):
    class Stream(object):

        itags = {
            '5': ('320x240', 'flv', "normal"),
            '17': ('176x144', '3gp', "normal"),
            '18': ('640x360', 'mp4', "normal"),
            '22': ('1280x720', 'mp4', "normal"),
            '34': ('640x360', 'flv', "normal"),
            '35': ('854x480', 'flv', "normal"),
            '36': ('320x240', '3gp', "normal"),
            '37': ('1920x1080', 'mp4', "normal"),
            '38': ('4096x3072', 'superHD', "normal"),
            '43': ('640x360', 'webm', "normal"),
            '44': ('854x480', 'webm', "normal"),
            '45': ('1280x720', 'webm', "normal"),
            '46': ('1920x1080', 'webm', "normal"),
            '82': ('640x360-3D', 'mp4', "normal"),
            '84': ('1280x720-3D', 'mp4', "normal"),
            '100': ('640x360-3D', 'webm', "normal"),
            '102': ('1280x720-3D', 'webm', "normal"),
            '133': ('426x240', 'm4v', 'video'),
            '134': ('640x360', 'm4v', 'video'),
            '135': ('854x480', 'm4v', 'video'),
            '136': ('1280x720', 'm4v', 'video'),
            '137': ('1920x1080', 'm4v', 'video'),
            '138': ('4096x3072', 'm4v', 'video'),
            '139': ('48k', 'm4a', 'audio'),
            '140': ('128k', 'm4a', 'audio'),
            '141': ('256k', 'm4a', 'audio'),
            '160': ('256x144', 'm4v', 'video'),
            '171': ('128k', 'ogg', 'audio'),
            '172': ('192k', 'ogg', 'audio'),
            '247': ('unknown', 'unknown', 'unknown'),
            '248': ('unknown', 'unknown', 'unknown')
        }

        def __init__(self, sm, title="ytvid", js=None):

            self.url = sm['url'][0]
            #print sm
            if not "signature=" in self.url:
                self.url += '&signature=' + sm['sig'][0]

            if not "ratebypass=" in self.url:
                self.url = self.url + "&ratebypass=yes"
            self.itag = sm['itag'][0]
            
            #pprint.pprint(self.url)
            #print "\n\n"
            
            
            self.resolution = self.itags[self.itag][0]
            self.extension = self.itags[self.itag][1]
            self.title = title
            self.filename = self.title + "." + self.extension
            #aaa = [x for x in self.url.split("\n")]
            self.fsize = None#aaa
            self.mediatype = self.itags[self.itag][2]

        def get_filesize(self):

            if not self.fsize:

                try:
                    opener = self._opener
                    cl = "content-length"
                    self.fsize = int(opener.open(self.url).headers[cl])

                except (HTTPError, URLError):
                    self.fsize = 0

            return self.fsize

        def download(self, filepath="", quiet=False, callback=None):

                status_string = (' {:,} Bytes [{:.2%}] received. Rate: [{:4.0f} '
                                 'kbps]. ETA: [{:.0f} secs]')
                response = self._opener.open(self.url)
                total = int(response.info()['Content-Length'].strip())
                chunksize, bytesdone, t0 = 16384, 0, time.time()
                fname = filepath or self.filename

                try:
                    outfh = open(fname, 'wb')

                except IOError:
                    ok = re.compile(r'[^\\/?*$\'"%&:<>|]')
                    fname = "".join(x if ok.match(x) else "_" for x in self.filename)
                    outfh = open(fname, 'wb')

                while True:
                    chunk = response.read(chunksize)
                    outfh.write(chunk)
                    elapsed = time.time() - t0
                    bytesdone += len(chunk)
                    rate = (bytesdone / 1024) / elapsed
                    eta = (total - bytesdone) / (rate * 1024)
                    progress_stats = (bytesdone, bytesdone * 1.0 / total, rate, eta)

                    if not chunk:
                        outfh.close()
                        break

                    if not quiet:
                        status = status_string.format(*progress_stats)
                        sys.stdout.write("\r" + status + ' ' * 4 + "\r")
                        sys.stdout.flush()

                    if callback:
                        callback(total, *progress_stats)

                return fname
    class vv():


        def __init__(self,ID):

            self.video_url = "http://www.youtube.com/watch?v="+ID
            self.infoUrl = 'https://www.youtube.com/get_video_info?video_id='
            
            m = re.search(r'\bv=([a-zA-Z0-9-_]{11})', self.video_url)
            if not m:
                m = re.search(r'\b([a-zA-Z0-9-_]{11})', self.video_url)

            if not m:
                err = "Need 11 character video id or the URL of the video. Got %s"
                raise RuntimeError(err % self.video_url)
            #print dir(m)
            self.vidid = m.group(1)
            self.vidid = ID
            self.infoUrl += self.vidid + "&asv=3&el=detailpage&hl=en_US"

            opener = ""
            keywords = ""
            self.allinfo = parse_qs(urlopen(self.infoUrl).read())

            #print self.allinfo["title"][0]
            f = lambda x: self.allinfo.get(x, ["unknown"])[0]

            self.gdata = None
            self.xargs = None
            self.js = None
            self.title = f('title').replace("/", "-")
            self.videoid = f('video_id')
            self.length = int(f('length_seconds'))
            #print self.length
            smap, js = self.getstreammap(
                    self.allinfo, 'url_encoded_fmt_stream_map')

            self.streams = [Stream(sm, self.title, self.js) for sm in smap]




        def getstreammap(self,allinfo, key):

            streamMap = self.allinfo[key][0].split(',')
            smap = [parse_qs(sm) for sm in streamMap]
            if smap[0].get("s"):
                streamMap = args[key].split(",")
                smap = [parse_qs(sm) for sm in streamMap]
            return(smap, self.js)




        def getbest(self,preftype="any", ftypestrict=True):
            def _sortkey(x, key3d=0, keyres=0, keyftype=0):
                key3d = "3D" not in x.resolution
                keyres = int(x.resolution.split("x")[0])
                keyftype = preftype == x.extension

                if ftypestrict:
                    return (key3d, keyftype, keyres)

                else:
                    return (key3d, keyres, keyftype)

            r = max(self.streams, key=_sortkey)

            if ftypestrict and preftype != "any" and r.extension != preftype:
                return None

            else:
                return r

    bb = vv(ID).getbest(preftype="mp4", ftypestrict=True)
    return bb

if __name__ == '__main__':
   print json.dumps(saxli(sys.argv[1]).__dict__)

