#!python
"""
    * ytmdl.py - A script to download songs.

----------------------------------------------------
     A simple script to download songs in mp3 format
     from Youtube.
     Users pass the song name as arguments.
----------------------------------------------------
    --> Deepjyoti Barman
    --> deepjyoti30@github.com
"""

from __future__ import unicode_literals
import sys
from colorama import init
from colorama import Fore, Style
import argparse
from ytmdl import (
            dir,
            song,
            yt,
            defaults,
            prepend,
            setupConfig,
            cache,
            utility,
            metadata,
            logger
)

# init colorama for windows
init()

logger = logger.Logger('ytmdl')


def arguments():
    """Parse the arguments."""
    parser = argparse.ArgumentParser()

    parser.add_argument('SONG_NAME', help="Name of the song to download.",
                        type=str, nargs="*")
    parser.add_argument('-q', '--quiet',
                        help="Don't ask the user to select songs\
                        if more than one search result.\
                        The first result in each case will be considered.",
                        action='store_true')
    metadata_group = parser.add_argument_group("Metadata")
    metadata_group.add_argument(
                        '--song', help="The song to search in Metadata. \
                        Particularly useful for songs that have the names in a\
                        different language in YouTube. For Example, greek songs.",
                        metavar='SONG-METADATA', default=None)
    metadata_group.add_argument(
                        '--choice', help="The choice that the user wants\
                        to go for. Usefull to pass along with --quiet.\
                        Choices start at 1", choices=range(1,50),
                        type=int, default=None, metavar="CHOICE")
    metadata_group.add_argument(
                        '--artist', help="The name of the song's artist.\
                        Pass it with a song name.")
    metadata_group.add_argument(
                        '--album', help="The name of the song's album.\
                        Pass it with a song name.")
    metadata_group.add_argument('--disable-metaadd', help="Disable addition of\
                        passed artist and album keyword to the youtube search\
                        in order to get a more accurate result. (Default: false)",
                        action="store_true")

    parser.add_argument('--proxy', help='Use the specified HTTP/HTTPS/SOCKS proxy. To enable '
                        'SOCKS proxy, specify a proper scheme. For example '
                        'socks5://127.0.0.1:1080/. Pass in an empty string (--proxy "") '
                        'for direct connection', default=None, metavar='URL')
    parser.add_argument('--url',
                        help="Youtube song link.")
    parser.add_argument('-s', '--setup',
                        help='Setup the config file',
                        action='store_true')
    parser.add_argument('--list', help="Download list of songs.\
                        The list should have one song name in every line.",
                        default=None, metavar="path to list".upper())
    parser.add_argument('--nolocal',
                        help='Don\'t search locally for the song before\
                        downloading.',
                        action='store_true')
    parser.add_argument('--version', action='version', version='2020.03.21',
                        help='show the program version number and exit')
    
    logger_group = parser.add_argument_group("Logger")
    logger_group.add_argument(
        "--level",
        help="The level of the logger that will be used while verbosing.\
            Use `--list-level` to check available options." + "\n",
        default="INFO",
        type=str
    )
    logger_group.add_argument(
        "--disable-file",
        help="Disable logging to files",
        default=False,
        action="store_true",
    )
    logger_group.add_argument(
        "--list-level",
        help="List all the available logger levels.",
        action="store_true"
    )

    args = parser.parse_args()

    return args


def main(args):
    """Run on program call."""

    # Check if --setup is passed
    if args.setup:
        setupConfig.make_config()
        exit(0)

    if args.list_level:
        logger.list_available_levels()
        exit(0)

    # Update the logger flags, in case those are not the default ones.
    if args.level.lower != "info":
        logger.update_level(args.level.upper())

    if args.disable_file:
        logger.update_disable_file(True)
        logger.debug("Writing logs to file disabled")

    # Just a message to make the user aware of the current running state
    logger.debug("Logger running in DEBUG mode")

    if not args.SONG_NAME:
        logger.critical("Song Name is required. Check 'ytmdl --help' for help.")

    logger.debug(len(args.SONG_NAME))
    if len(args.SONG_NAME) > 1:
        song_name = ' '.join(args.SONG_NAME)
    else:
        song_name = args.SONG_NAME[0]

    logger.debug(song_name)

    if not args.nolocal:
        # Search for the song locally
        if not cache.main(song_name):
            return 0

    # Check if ffmpeg is installed.
    if not utility.is_present('ffmpeg'):
        logger.critical("ffmpeg is not installed. Please install it!")

    # Check if youtube-dl is installed.
    if not utility.is_present('youtube-dl'):
        logger.critical("youtube-dl is not installed. Please install it!")

    is_quiet = args.quiet
    url = args.url
    passed_choice = args.choice

    logger.debug("proxy passed: {}".format(args.proxy))

    if args.song is not None:
        song_metadata = args.song
    else:
        song_metadata = song_name

    # If the url is passed then get the data
    if url is not None:
        data = []
        # Get video data from youtube
        temp_data = yt.scan_video(yt.get_href(url), args.proxy)
        data.append(temp_data)

        # link to dw the song
        link = url

        # In this case choice will be 0
        choice = 0
    else:
        if is_quiet:
            logger.info('Quiet is enabled')

        logger.info('Searching Youtube for {}{}{}'.format(
                Fore.LIGHTYELLOW_EX,
                song_name,
                Style.RESET_ALL
        ))

        data = yt.search(song_name, not args.disable_metaadd,
                                args.proxy,
                                kw=[args.artist, args.album])
        
        # Handle the exception if urls has len 0
        if len(data) == 0:
            logger.critical("No song found. Please try again with a different keyword.")

        if not is_quiet:
            # Ask for a choice
            choice = song.getChoice(data, 'mp3')
        else:
            if passed_choice is not None and passed_choice <= len(data):
                choice = passed_choice - 1
                logger.info("Using {} as choice".format(passed_choice))
            else:
                choice = 0

        link = 'https://youtube.com{}'.format(data[int(choice)]['href'])

    # Declare a var to store the name of the yt video
    yt_title = data[choice]['title']

    logger.info('Downloading {}{}{} in {}{}kbps{}'.format(
        Fore.LIGHTMAGENTA_EX,
        yt_title,
        Style.RESET_ALL,
        Fore.LIGHTYELLOW_EX,
        defaults.DEFAULT.SONG_QUALITY,
        Style.RESET_ALL
    ))
    path = yt.dw(link, args.proxy, yt_title)

    if type(path) is not str:
        logger.critical("ERROR: {}".format(path))
    else:
        logger.info('Downloaded!')

    logger.info('Converting to mp3...')

    conv_name = utility.convert_to_mp3(path)

    if type(conv_name) is not str:
        logger.critical('ERROR: {}'.format(conv_name))

    logger.info('Getting song data for {}...'.format(song_metadata))

    TRACK_INFO = metadata.SEARCH_SONG(song_metadata, filters=[args.artist, args.album])

    # declare a variable to store the option
    option = 0

    if TRACK_INFO is False:
        # prepend.PREPEND(2)
        # print('Data \a')
        # exit(0)
        pass
    elif len(TRACK_INFO) == 0:
        logger.critical('No data was found!\a')
    else:
        prepend.PREPEND(1)
        print('Setting data...')

        option = song.setData(TRACK_INFO, is_quiet, conv_name, passed_choice)

        if type(option) is not int:
            logger.critical('ERROR: {}'.format(option))

    # Get the directory where song is moved

    DIR = dir.cleanup(TRACK_INFO, option)
    logger.info('Moving to {}...'.format(DIR))

    if type(DIR) is not str:
        logger.critical('ERROR: {}'.format(DIR))
    else:
        logger.info('Done')


def extract_data():
    """Extract the arguments and act accordingly."""
    args = arguments()

    if args.list is not None:
        songs = utility.get_songs(args.list)
        logger.debug(str(songs))
        if len(songs) != 0:
            logger.info("Downloading songs in {}".format(args.list))
            for song_name in songs:
                logger.debug(song_name)
                args.SONG_NAME = [song_name]
                main(args)
        else:
            logger.info("{}: is empty".format(args.list))
    else:
        main(args)


if __name__ == '__main__':
    try:
        extract_data()
    except KeyboardInterrupt:
        logger.info("\nExiting..!")
