#!/usr/bin/python

''' PAFY - Command Line Downloader Tool - ytdl
    Copyright (C)  2013 nagev

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU 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 General Public License for more details.

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

__version__ = "0.3.20"
__author__ = "nagev"
__license__ = "GPLv3"

from pafy import Pafy
import argparse
import sys


def download(video, stream=None):
    if not stream:
        stream = video.getbest(preftype="mp4")
    size = stream.get_filesize()
    print("-Downloading '{}' [{:,} Bytes]".format(stream.filename, size))
    print("-Quality: %s; Format: %s" % (stream.quality, stream.extension))
    stream.download(quiet=False)
    print("\nDone")


def printstreams(vid):
    fstring = "{:<7}{:<8}{:<7}{:<16}{:<10}"
    print(fstring.format("Stream", "Type", "Format", "Quality", " Size"))
    print(fstring.format("------", "----", "------", "-------", " ----"))
    for n, s in enumerate(vid.allstreams):
        megs = "%3.f" % (s.get_filesize() / 1024 ** 2) + " MB"
        q = "[%s]" % s.quality
        print(fstring.format(n + 1, s.mediatype, s.extension, q, megs))


def main():
    description = "YouTube Download Tool"
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument('url', help="YouTube video URL to download")
    parser.add_argument('-i', required=False, help="Display vid info",
                        action="store_true")
    parser.add_argument('-s', help="Display available streams", action=
                        "store_true")
    fq = parser.add_argument_group(
        "format and quality", description="Specify the stream to download by"
        " quality (ie. resolution or bitrate) and file format"
    )
    fq.add_argument(
        '-f', type=str, help='format of the file to download',
        required=False, choices='webm mp4 3gp flv m4v m4a ogg'.split()
    )
    fq.add_argument('-q', type=str, help='quality of the file to download',
                    required=False, metavar='{NNN}x{NNN} | {NNN}k')
    parser.add_argument(
        '-n', required=False, metavar="N", type=int, help="Specify stream to "
        "download by stream number (use -s to list, ignores -f and -q)"
    )
    parser.add_argument(
        '-b', required=False, help='Download the best quality video (ignores '
        '-n, -f and -q)', action="store_true"
    )

    args = parser.parse_args()
    vid = Pafy(args.url)
    # quality and format, if present, must both be present.
    if args.f and not args.q or args.q and not args.f:
        parser.print_help()
        sys.exit("\n-f and -q cannot be used independently of each other!")
    # if requested print vid info and list streams
    if args.i:
        print(vid)
    if args.s:
        printstreams(vid)
    if args.b:
        if args.n:
            print("-b and -n cannot be used together! Use one or the other.")
        else:
            download(vid)
            sys.exit()
    elif args.n:
        streamnumber = int(args.n) - 1
        download(vid, vid.allstreams[streamnumber])

    elif args.f and args.q:
        print((args.f, args.q))
        print("Getting streams...")
        matchres, matchformat = 0, 0
        for n, stream in enumerate(vid.allstreams):
            if args.f == stream.extension:
                matchformat = 1
                if str(args.q) in stream.quality:
                    matchres = 1
                    # matching video found, download it
                    download(vid, stream)
        if not matchres:
            print("No stream found matching resolution " + str(args.q) +
                  ". Try checking available resolutions using '-s'")
        if not matchformat:
            print("no stream found matching format %s" % str(args.f) +
                  ". Try checking available formats using '-s'")
    if not args.i and not args.s and not args.b and not args.n and not args.q:
        print("Nothing to do!  Try -b to download highest quality or"
              " -s to list available streams")


main()
