# -*- coding: utf-8-*-
import subprocess
import os
import platform
from . import utils, logging
import _thread as thread
from ctypes import CFUNCTYPE, c_char_p, c_int, cdll
from contextlib import contextmanager

logger = logging.getLogger(__name__)

def py_error_handler(filename, line, function, err, fmt):
    pass

ERROR_HANDLER_FUNC = CFUNCTYPE(None, c_char_p, c_int, c_char_p, c_int, c_char_p)

c_error_handler = ERROR_HANDLER_FUNC(py_error_handler)

@contextmanager
def no_alsa_error():
    try:
        asound = cdll.LoadLibrary('libasound.so')
        asound.snd_lib_error_set_handler(c_error_handler)
        yield
        asound.snd_lib_error_set_handler(None)
    except:
        yield
        pass

def play(fname, onCompleted=None, wait=False):
    player = getPlayerByFileName(fname)
    player.play(fname, onCompleted=onCompleted, wait=wait)

def getPlayerByFileName(fname):
    foo, ext = os.path.splitext(fname)
    if ext in ['.mp3', '.wav']:
        return SoxPlayer()

class AbstractPlayer(object):

    def __init__(self, **kwargs):
        super(AbstractPlayer, self).__init__()

    def play(self):
        pass

    def play_block(self):
        pass

    def stop(self):
        pass

    def is_playing(self):
        return False
    

class SoxPlayer(AbstractPlayer):
    SLUG = 'SoxPlayer'

    def __init__(self, **kwargs):
        super(SoxPlayer, self).__init__(**kwargs)
        self.playing = False
        self.proc = None
        self.delete = False
        self.onCompleteds = []

    def doPlay(self):
        cmd = ['play', str(self.src)]
        logger.debug('Executing %s', ' '.join(cmd))
        self.proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        self.playing = True
        self.proc.wait()
        self.playing = False
        if self.delete:
            utils.check_and_delete(self.src)
        logger.debug('play completed')
        if self.proc.returncode == 0:
            for onCompleted in self.onCompleteds:
                if onCompleted is not None:
                    onCompleted()
    
    def play(self, src, delete=False, onCompleted=None, wait=False):
        if os.path.exists(src) or src.startswith('http'):
            self.src = src
            self.delete = delete
            if onCompleted is not None:
                self.onCompleteds.append(onCompleted)
            if not wait:
                thread.start_new_thread(self.doPlay, ())
            else:
                self.doPlay()
        else:
            logger.critical('path not exists: {}'.format(src))

    def appendOnCompleted(self, onCompleted):
        if onCompleted is not None:
            self.onCompleteds.append(onCompleted)

    def play_block(self):
        self.run()

    def stop(self):
        if self.proc:
            self.onCompleteds = []
            self.proc.terminate()
            if self.delete:
                utils.check_and_delete(self.src)

    def is_playing(self):
        return self.playing


class MusicPlayer(SoxPlayer):
    """
    给音乐播放器插件使用的，
    在 SOXPlayer 的基础上增加了列表的支持，
    并支持暂停和恢复播放
    """
    SLUG = 'MusicPlayer'

    def __init__(self, playlist, plugin, **kwargs):
        super(MusicPlayer, self).__init__(**kwargs)
        self.playlist = playlist
        self.plugin = plugin
        self.idx = 0
        self.pausing = False
        self.last_paused = None

    def update_playlist(self, playlist):
        super().stop()
        self.playlist = playlist
        self.idx = 0
        self.play()

    def play(self):
        logger.debug('MusicPlayer play')
        path = self.playlist[self.idx]
        super().stop()
        super().play(path, False, self.next)

    def next(self):
        logger.debug('MusicPlayer next')
        super().stop()
        self.idx = (self.idx+1) % len(self.playlist)
        self.play()

    def prev(self):
        logger.debug('MusicPlayer prev')
        super().stop()
        self.idx = (self.idx-1) % len(self.playlist)
        self.play()

    def pause(self):
        logger.debug('MusicPlayer pause')
        self.pausing = True

    def stop(self):
        if self.proc:
            logger.debug('MusicPlayer stop')
            # STOP current play process
            self.last_paused = utils.write_temp_file(str(self.proc.pid), 'pid', 'w')
            self.onCompleteds = []
            subprocess.run(['pkill', '-STOP', '-F', self.last_paused])

    def resume(self):
        logger.debug('MusicPlayer resume')
        self.pausing = False
        self.onCompleteds = [self.next]
        if self.last_paused is not None:
            print(self.last_paused)
            subprocess.run(['pkill', '-CONT', '-F', self.last_paused])

    def is_playing(self):
        return self.playing

    def is_pausing(self):
        return self.pausing

    def turnUp(self):
        system = platform.system()
        if system == 'Darwin':
            res = subprocess.run(['osascript', '-e', 'output volume of (get volume settings)'], shell=False, capture_output=True, universal_newlines=True)
            volume = int(res.stdout.strip())
            volume += 20
            if volume >= 100:
                volume = 100
                self.plugin.say('音量已经最大啦', wait=True)
            subprocess.run(['osascript', '-e', 'set volume output volume {}'.format(volume)])
        elif system == 'Linux':
            res = subprocess.run(["amixer sget Master | grep 'Mono:' | awk -F'[][]' '{ print $2 }'"], shell=True, capture_output=True, universal_newlines=True)
            print(res.stdout)
            if res.stdout != '' and res.stdout.strip().endswith('%'):
                volume = int(res.stdout.strip().replace('%', ''))
                volume += 20
                if volume >= 100:
                    volume = 100
                    self.plugin.say('音量已经最大啦', wait=True)
                subprocess.run(['amixer', 'set', 'Master', '{}%'.format(volume)])
            else:
                subprocess.run(['amixer', 'set', 'Master', '20%+'])
        else:
            self.plugin.say('当前系统不支持调节音量', wait=True)
        self.resume()

    def turnDown(self):
        system = platform.system()
        if system == 'Darwin':
            res = subprocess.run(['osascript', '-e', 'output volume of (get volume settings)'], shell=False, capture_output=True, universal_newlines=True)
            volume = int(res.stdout.strip())
            volume -= 20
            if volume <= 20:
                volume = 20
                self.plugin.say('音量已经很小啦', wait=True)
            subprocess.run(['osascript', '-e', 'set volume output volume {}'.format(volume)])
        elif system == 'Linux':
            res = subprocess.run(["amixer sget Master | grep 'Mono:' | awk -F'[][]' '{ print $2 }'"], shell=True, capture_output=True, universal_newlines=True)
            if res.stdout != '' and res.stdout.endswith('%'):
                volume = int(res.stdout.replace('%', '').strip())
                volume -= 20
                if volume <= 20:
                    volume = 20
                    self.plugin.say('音量已经最小啦', wait=True)
                subprocess.run(['amixer', 'set', 'Master', '{}%'.format(volume)])
            else:
                subprocess.run(['amixer', 'set', 'Master', '20%-'])
        else:
            self.plugin.say('当前系统不支持调节音量', wait=True)
        self.resume()
