'''The play queue.'''

from os import path
import shlex
from subprocess import run
from threading import Thread, Lock

import click
from youtube_dl import YoutubeDL, utils

import fediplay.env as env


class Queue(object):
    '''The play queue.'''

    # pylint: disable=too-few-public-methods

    def __init__(self, cache_dir):
        self.lock = Lock()
        self.playing = False
        self.queue = []
        self.cache_dir = cache_dir

    def add(self, url):
        '''Fetches the url and adds the resulting audio to the play queue.'''

        filenames = Getter(self.cache_dir).get(url)

        with self.lock:
            self.queue.extend(filenames)
            if not self.playing:
                self._play(self.queue.pop(0), self._play_finished)

    def _play(self, filename, cb_complete):
        self.playing = True

        def _run_thread(filename, cb_complete):
            play_command = build_play_command(filename)
            click.echo('==> Playing {} with {}'.format(filename, play_command))
            run(play_command, shell=True)
            click.echo('==> Playback complete')
            cb_complete()

        thread = Thread(target=_run_thread, args=(filename, cb_complete))
        thread.start()

    def _play_finished(self):
        with self.lock:
            self.playing = False
            if self.queue:
                self._play(self.queue.pop(0), self._play_finished)

class Getter(object):
    '''Fetches music from a url.'''

    # pylint: disable=too-few-public-methods

    def __init__(self, cache_dir):
        self.filename = None
        self.filenames = []
        self.cache_dir = cache_dir

    def _progress_hook(self, progress):
        if progress['status'] == 'downloading' and progress['filename'] not in self.filenames:
            self.filenames.append(progress['filename'])

    def get(self, url):
        '''Fetches music from the given url.'''

        options = {
            'format': 'mp3/mp4',
            'nocheckcertificate': env.no_check_certificate(),
            'outtmpl': path.join(self.cache_dir, utils.DEFAULT_OUTTMPL),
            'progress_hooks': [self._progress_hook]
        }
        with YoutubeDL(options) as downloader:
            downloader.download([url])

        return self.filenames

def build_play_command(filename):
    '''Builds a play command for the given filename.'''

    escaped_filename = shlex.quote(filename)
    template = env.play_command()
    return template.format(filename=escaped_filename)