import logging
from os import listdir, makedirs, remove
from os.path import abspath, dirname, join, sep, isfile
from shutil import rmtree
from urllib.request import urlretrieve

from django.conf import settings
from owltail.api_handler import APIHandler

BASE_DIR = dirname(abspath(__file__))
logger = logging.getLogger(__name__)
default_api_handler = APIHandler()


class SongsSynchroniser:
    def __init__(self, api_handler=default_api_handler, *args, **kwargs):
        self.api_handler = api_handler
        self.songs_folder = kwargs.get(
            'songs_folder', settings.DEFAULT_SONGS_FOLDER
        )

    def start(self):
        logger.info('Starting songs synchro')
        previous_themes = listdir(settings.DEFAULT_SONGS_FOLDER)
        themes = self.api_handler.get_themes()
        current_themes = []

        # create new folder and synchronise_songs
        for theme in themes:
            name = theme['name']
            current_themes.append(name)
            theme_folder = join(self.songs_folder, name)
            logger.debug(
                'Creating (if needed) songs folder {}'.format(theme_folder)
            )
            makedirs(theme_folder, exist_ok=True)
            logger.debug(
                'Synchronising songs for folder {}'.format(theme_folder)
            )
            self.synchronise_songs(theme_folder, theme['songs'])

        # delete old folders
        for previous_theme in previous_themes:
            if previous_theme not in current_themes:
                previous_theme_folder = join(self.songs_folder, previous_theme)
                logger.debug(
                    'Deleting songs folder {}'.format(previous_theme_folder)
                )
                rmtree(previous_theme_folder)

        logger.debug('Finished songs synchro')

    def synchronise_songs(self, theme_folder, songs):
        if not songs:
            rmtree(theme_folder)
            return
        filenames = [self.extract_filename(song['url']) for song in songs]
        for existing_file in listdir(theme_folder):
            if existing_file not in filenames:
                song_removed = join(theme_folder, existing_file)
                logger.debug('Deleting song {}'.format(song_removed))
                remove(song_removed)

        for song in songs:
            full_filename = join(
                theme_folder, self.extract_filename(song['url'])
            )
            if not isfile(full_filename):
                logger.debug('Downloading song from {}'.format(song['url']))
                urlretrieve(song['url'], full_filename)

    def extract_filename(self, url):
        bits = url.split(sep)
        return bits[-1]
