#!/usr/bin/env python2.7

"""
    Download youtube videos and open them after finish in an infinite cycle.
"""

import os
import re
import sys
import time
import webbrowser
import subprocess as sp
from contextlib import closing
import threading


PROMPT = 'Link to download: '

CARRIAGE_BACK = '\r'
NEW_LINE = '\n'
ESC = '\x1b'
# https://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements
CSI = ESC + '['
CLEAR_LINE = CSI + 'K'
CURSOR_UP = CSI + 'A'
CURSOR_FOWRWARD = CSI + 'C'

jobs = []

down_re = re.compile(r'\[download\] (?P<filename>.*) has already been downloaded')
dest_re = re.compile(r'Destination: (?P<filename>.*)$', re.MULTILINE)


def writeout(line, prompt=True):
    sys.stdout.write(CURSOR_UP + NEW_LINE + line)
    if prompt:
        sys.stdout.write(PROMPT)
    sys.stdout.flush()


def print_and_save_output(proc):
    output = []
    while proc.poll() is None:
        line = proc.stdout.readline()
        if line.startswith('[download]') and 'ETA' in line:
            line = CURSOR_UP + CARRIAGE_BACK + CLEAR_LINE + line.strip() + NEW_LINE
        writeout(line)
        output.append(line)
    writeout(NEW_LINE * 2)
    return ''.join(output)


class ProcessJobsThread(threading.Thread):
    """Download one video at a time from the jobs list."""
    daemon = True

    def run(self):
        while True:
            if not jobs:
                time.sleep(0.1)
                continue
            link = jobs.pop(0)
            params = ['youtube-dl', link]
            proc = sp.Popen(params, stdout=sp.PIPE, stderr=sp.STDOUT, universal_newlines=True)
            output = print_and_save_output(proc)
            m = down_re.search(output)
            if not m:
                m = dest_re.search(output)
            webbrowser.open(m.group('filename'))


def main():
    while True:
        writeout('Folder: %s\n' % os.getcwd())
        link = raw_input()
        if not link:
            sys.stdout.write('\n')
            sys.stdout.flush()
            continue
        elif not link.startswith('http'):
            writeout('Not a link: %s\n\n' % link, prompt=False)
            continue
        jobs.append(link)
        writeout('Link added to the queue: %s\n' % link, prompt=False)


if __name__ == '__main__':
    try:
        ProcessJobsThread().start()
        main()
    except (KeyboardInterrupt, EOFError):
        pass
