#!/usr/bin/env python3
# -*- coding: utf-8 -*-

__name__ = "SpotifyDL"

import subprocess
from configparser import ConfigParser
import os.path
import logging
from enum import Enum


defaultCredentialsLocation = '../config/zspotify.credentials'


class SpotifyDLStatus(Enum):
    NONE = "none"
    RUNNING = "running"
    FINISHED = "finished"
    ERROR = "error"
    DISABLED = "disabled"


class SpotifyDL():

    def __init__(self, luniebox, credentialsLocation=defaultCredentialsLocation):

        if not luniebox.zspotify_path:
            raise ValueError("No zspotify path provivded!")
        else:
            self.zspotify_path = luniebox.zspotify_path

        if credentialsLocation:
            self.credentialsLocation = credentialsLocation
        else:
            raise ValueError("No credentialsLocation provivded!")

        username = luniebox.spotify.get_setting("username")
        if not username:
            raise ValueError("No username provided!")

        password = luniebox.spotify.get_setting("password")
        if not password:
            raise ValueError("No password provided!")

        root = luniebox.get_setting('mpd', 'library_path')
        if root:
            if not root.endswith("/"):
                root = root + "/"
            self.root = root
        else:
            raise ValueError("No root provided!")

        if not os.path.isfile(self.credentialsLocation):
            logging.getLogger('luniebox').info("initialize zspotify")
            p = subprocess.Popen([self.zspotify_path + 'venv/bin/python', self.zspotify_path + 'zspotify/__main__.py', '-s',
                                 '--credentials-location', self.credentialsLocation], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, shell=False, group="pi", user="pi")
            input = username + '\n' + password + '\n'
            out, err = p.communicate(input=input.encode())
            logging.getLogger('luniebox').info(out)
            logging.getLogger('luniebox').warn(err)

        self.downloads = {}

    def download(self, uri):
        status = self.downloadStatus(uri)
        if status == SpotifyDLStatus.NONE or status == SpotifyDLStatus.ERROR:
            logging.getLogger('luniebox').info(
                "start download of '" + uri + "'")
            trackprefix = ""
            if uri.startswith('spotify:album:'):
                trackprefix = "{album_num}. "
            elif uri.startswith('spotify:playlist:'):
                trackprefix = "{playlist_num}. "
            p = subprocess.Popen([self.zspotify_path + 'venv/bin/python', self.zspotify_path + 'zspotify/__main__.py', "--root-path", self.root,
                                 '--credentials-location', self.credentialsLocation, "--download-real-time", "True", "--chunk-size", "50000", "--skip-existing-files", "True", "--skip-previously-downloaded", "True", "--output",  uri + "/" + trackprefix + "{artist} - {song_name}.{ext}", uri], stdin=None,
                                 stdout=None, stderr=None, close_fds=True, shell=False, group="pi", user="pi")
            self.downloads[uri] = p
            return SpotifyDLStatus.RUNNING
        elif status == SpotifyDLStatus.RUNNING:
            logging.getLogger('luniebox').debug(
                "download for '" + uri + "' still running")
        elif status == SpotifyDLStatus.FINISHED:
            logging.getLogger('luniebox').debug(
                "alreaded downloaded '" + uri + "'")
        return status

    def downloadStatus(self, uri):
        doneFiledPath = self.root + uri + '/.spotifydl'
        if uri in self.downloads:
            if self.downloads[uri]:
                poll = self.downloads[uri].poll()
                if poll != None:
                    self.downloads.pop(uri)
                    if poll == 0:
                        p = subprocess.Popen(["touch", doneFiledPath], stdin=None,
                                             stdout=None, stderr=None, close_fds=True, shell=False, group="pi", user="pi")
                        p.communicate()
                        return SpotifyDLStatus.FINISHED
                    logging.getLogger('luniebox').warn(
                        "download of '" + uri + "' exited with: " + str(poll))
                    return SpotifyDLStatus.ERROR
            return SpotifyDLStatus.RUNNING

        if os.path.exists(doneFiledPath):
            return SpotifyDLStatus.FINISHED

        return SpotifyDLStatus.NONE

    def getDownloads(self):
        downloads = {}
        for uri in self.downloads.keys():
            downloads[uri] = str(self.downloadStatus(uri))
        return downloads
