#!/usr/bin/env python
############################################################################
#
# Author: Edgar Carrera
# May, 2012
############################################################################

"""
   usage: %prog [options]
   -f, --first = FIRST: Playlist starts at FIRST (default is FIRST = 1)
   -l, --last = LAST: Playlist ends at LAST (default is LAST = 9999)
   -x, --fix : just fix filenames, do not download anything
"""


import os,sys
import subprocess
import string, re
import fileinput
import commands
from time import gmtime, localtime, strftime

#flag to debug
DEBUG = True
printConfig = True

# _____________________OPTIONS_______________________________________________

############################################################################
# Code taken from http://code.activestate.com/recipes/278844/
############################################################################
import optparse
USAGE = re.compile(r'(?s)\s*usage: (.*?)(\n[ \t]*\n|$)')
def nonzero(self): # will become the nonzero method of optparse.Values
    "True if options were given"
    for v in self.__dict__.itervalues():
        if v is not None: return True
    return False

optparse.Values.__nonzero__ = nonzero # dynamically fix optparse.Values

class ParsingError(Exception): pass

optionstring=""

def exit(msg=""):
    raise SystemExit(msg or optionstring.replace("%prog",sys.argv[0]))

def parse(docstring, arglist=None):
    global optionstring
    optionstring = docstring
    match = USAGE.search(optionstring)
    if not match: raise ParsingError("Cannot find the option string")
    optlines = match.group(1).splitlines()
    try:
        p = optparse.OptionParser(optlines[0])
        for line in optlines[1:]:
            opt, help=line.split(':')[:2]
            short,long=opt.split(',')[:2]
            if '=' in opt:
                action='store'
                long=long.split('=')[0]
            else:
                action='store_true'
            p.add_option(short.strip(),long.strip(),
                         action = action, help = help.strip())
    except (IndexError,ValueError):
        raise ParsingError("Cannot parse the option string correctly")
    return p.parse_args(arglist)


#_________________________________________________________________________


#######################################################
def download_videos_and_convert_to_mp3(dicOpt):
#######################################################
    firstVid = dicOpt['first']
    lastVid = dicOpt['last']
    urlString = dicOpt['url']

    do_youtube_dl = "youtube-dl -l -i --extract-audio --audio-format mp3 --playlist-start "+firstVid+" --playlist-end "+lastVid+" '"+urlString+"'"

    
    print do_youtube_dl
    os.system(do_youtube_dl)
    fix_filenames()
    


#######################################################
def fix_filenames():
#######################################################
    print "Fixing filenames...."
    str_ls = "ls -1 *.mp3"
    mypipe = subprocess.Popen(str_ls,shell=True,stdout=subprocess.PIPE)
    files = mypipe.communicate()[0].split("\n")
    del files[len(files)-1]
    for xfile in files:
        cleanFile = xfile.replace(' ','\ ')
        cleanFile = cleanFile.replace('(','\(')
        cleanFile = cleanFile.replace(')','\)')
        cleanFile = cleanFile.replace('&','\&')
        cleanFile = cleanFile.replace('!','\!')
        cleanFile = cleanFile.replace("'","\\'")
        cleanFile = cleanFile.replace('@','\@')
        cleanFile = cleanFile.replace('#','\#')
        cleanFile = cleanFile.replace('$','\$')
        cleanFile = cleanFile.replace('%','\%')
        cleanFile = cleanFile.replace('^','\^')
        cleanFile = cleanFile.replace('&','\&')
        cleanFile = cleanFile.replace('*','\*')
        cleanFile = cleanFile.replace('+','\+')
        cleanFile = cleanFile.replace('=','\=')
        tempFile = cleanFile.split("-")
        newFile = ""
        #print tempFile
        for j in range(len(tempFile)-1):
            if j is not (len(tempFile)-2):
                newFile += tempFile[j].rstrip().lstrip()+"-"
                #print newFile
            else:
                newFile += tempFile[j].rstrip().lstrip()+".mp3"
                #print newFile
                
        #now make the renaming of files        
        str_mv = "mv "+cleanFile+" "+newFile
        #print "str_mv = "+str_mv
        os.system(str_mv)
        print "File "+xfile+" was renamed to "+newFile

#######################################################
def get_default_options(option):
#######################################################
    dicOpt = {}

    # first video in a video playlist
    if not option.first:
        dicOpt['first'] = "1"
    else:
        dicOpt['first'] = str(option.first)

    # last video in a video playlist
    if not option.last:
        dicOpt['last'] = "9999"
    else:
        dicOpt['last'] = str(option.last)

    # only fix mp3 names option
    if not option.fix:
        dicOpt['fix'] = False
    else:
        dicOpt['fix'] = True

    
    return dicOpt




#######################################################
if __name__ =='__main__':
#######################################################

    #import optionparser
    option,args = parse(__doc__)
    if not args and not option:
        exit()


    #print args[1]

    #set default options
    dicOpt = get_default_options(option)
    if (printConfig):
        for k in dicOpt:
            print str(k)+" = "+str(dicOpt[k])
            
    #check if no download is needed
    justFix = dicOpt['fix']

    #if download is needed, run the routine
    if(not justFix):
        dicOpt['url'] = str(args[0])
        download_videos_and_convert_to_mp3(dicOpt)
    else:
        fix_filenames()
    

            
    
    
    
    
    
