#Copyright 2015 Larbi Bekka

""" 
    fb-video-dl is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. 
"""

import sys
import os
import os.path
import urllib2
import re
import argparse
import progressbar as pb
import facebook


#parses command line arguments
def parse_args():
    parser = argparse.ArgumentParser(prog='fb-video-dl', description='download a facebook video')
    parser.add_argument('url', help='facebook video url')
    parser.add_argument('-o', '--output', help='specifies the output file')
    args = parser.parse_args()

    url = args.url

    if args.output:
        path = args.output
    else:
        path = ''

    #print args.output
    return url, path


#verifies the given path
def get_clifilename(path):
    if os.name == 'posix':
        sep = '/'
    elif os.name == 'nt':
        sep = '\\'

    split_path = os.path.split(path)
    abs_path = os.path.abspath(split_path[0])

    if not os.path.exists(abs_path):
       sys.exit('error : path '+abs_path+' does not exist')

    if split_path[1] == '':
        file_name = None
    else :
        file_name = split_path[1]
        print file_name

    return abs_path, file_name


#retrieves video id
def get_fvID(fburl):
    regex = 'http[s]?://www.facebook.[a-z]{2,3}/[A-Za-z0-9\.]*/videos/(vb.[0-9]+/){0,1}([0-9]+)*/'
    match = re.search(regex, fburl)


    if match:
        videoID = match.group(2)
        return videoID
    else:
        sys.exit('cannot find video ID')
        pass


#retrieves video info
def get_vidinfo(videoID):
    try:
        try:
            graph = facebook.GraphAPI()
            vidObject = graph.get_object(videoID)
            video_url = vidObject['source']
        except facebook.GraphAPIError:
            sys.exit('error : unable to reach facebook')


        url_h = urllib2.urlopen(video_url)
        meta  = url_h.info()
        size  = meta['Content-Length']
        content_type = meta['content-type']
        format = re.search('video/(\w+)', content_type).group(1)
        if vidObject.has_key('name'):
            filename = ''.join(e for e in vidObject['name'] if e.isalnum())
        else:
            filename = None
    except urllib2.URLError:
        sys.exit('error : unable to retrieve video info')


    info = {'url':video_url, 'name':filename, 'size':size, 'format':format}
    return info


#downloads the video
def dnl_vid(url, filename, size):
    try:
        file = open(filename, 'wb')
    except IOError:
        sys.exit('cannot access file '+filename)
    size = int(size)
    dsize = 0

    widgets = ['progress: ', pb.Percentage(), ' ', pb.Bar(marker=pb.RotatingMarker()), ' ', pb.ETA(), ' ', pb.FileTransferSpeed()]
    pbar = pb.ProgressBar(widgets=widgets, maxval=size).start()

    try:
        h_url = urllib2.urlopen(url)
    except urllib2.URLError:
        sys.exit('error : cannot open url')
    try:
        while True:
            info = h_url.read(8192)
            if len(info) < 1 :
                break
            dsize += len(info)
            file.write(info)
            pbar += len(info)

        pbar.finish()
    except IOError:
        sys.exit('error : unable to download the video')

    print 'done'
    pass


if __name__ == '__main__':
    #parsing command line arguments
    args = parse_args()
    url = args[0]
    path = args[1]
    #retrieving the absolute path and the filename if any
    pf_pair = get_clifilename(path)
    path = pf_pair[0]
    if path[-1] != '/':
        path += '/'
    file_name = pf_pair[1]

    print 'checking the url'
    videoID = get_fvID(url)
    print 'retrieving information'
    info = get_vidinfo(videoID)

    if file_name:
        file_name = path + file_name + '.' + info['format']
    elif info['name']:
        file_name = path + info['name'] + '.' + info['format']
    else:
        file_name = path + videoID + '.' + info['format']

    size = info['size']
    url = info['url']

    print 'destination : ',file_name
    if int(size) >= 1000000:
        print 'video size  : ', '{:.2f}'.format(int(size)/1024.0/1024), 'M'
    elif int(size) >= 1000:
        print 'video size  : ', '{:.2f}'.format(int(size)/1024.0), 'K'

    dnl_vid(url, file_name, size)
    sys.exit()