#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import signal
import time
import sys
import subprocess
import logging
from luniebox import luniebox
import RPi.GPIO as GPIO
from mpu9250_jmdev.registers import *
from mpu9250_jmdev.mpu_9250 import MPU9250


class LunieboxDaemon(object):

    def __init__(self, luniebox, input1=7, input2=8, skip_thresh=0.5, wind_thresh=0.3):
        signal.signal(signal.SIGINT, self.signal_handler)
        signal.signal(signal.SIGTERM, self.signal_handler)
        self.luniebox = luniebox
        self.input1 = input1
        self.input2 = input2
        self.skip_thresh = skip_thresh
        self.wind_thresh = wind_thresh
        GPIO.setup(self.input1, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.setup(self.input2, GPIO.IN, pull_up_down=GPIO.PUD_UP)

        self.tolerance = self.luniebox.get_setting(
            'rfid', 'pause_tolerance', 4)
        self.reads = 0
        self.error_text = False

        if self.luniebox.get_setting('hardware', 'mpu') == 'True':
            try:
                self.mpu = MPU9250(
                    address_ak=AK8963_ADDRESS,
                    address_mpu_master=MPU9050_ADDRESS_68,
                    address_mpu_slave=None,
                    bus=4,
                    gfs=GFS_1000,
                    afs=AFS_8G,
                    mfs=AK8963_BIT_16,
                    mode=AK8963_MODE_C100HZ)
                self.mpu.configure()
            except Exception as exception:
                logging.getLogger('luniebox').warning(
                    "Could not setup MPU9250: " + str(exception))
                self.mpu = False
        else:
            self.mpu = False

    def run(self):
        logging.getLogger('luniebox').info("run luniebox daemon")

        while True:
            # mpu
            if self.mpu:
                acc = self.mpu.readAccelerometerMaster()
                rot_x = acc[0]
                rot_y = acc[1]

                if rot_x > self.skip_thresh:
                    self.luniebox.previous()
                    time.sleep(1)
                elif rot_x < (self.skip_thresh * -1):
                    self.luniebox.next()
                    time.sleep(1)

                if rot_y < (self.wind_thresh * -1):
                    self.luniebox.fastforward()
                    time.sleep(0.1)
                elif rot_y > self.wind_thresh:
                    self.luniebox.rewind()
                    time.sleep(0.1)

            # buttons
            down_state = GPIO.input(self.input1)
            if down_state == False:
                self.luniebox.vol_down()
                time.sleep(0.1)

            up_state = GPIO.input(self.input2)
            if up_state == False:
                self.luniebox.vol_up()
                time.sleep(0.1)

            # rfid
            id, text = self.luniebox.reader.read_no_block()
            if text != None:
                text = text.strip()

            if text == None:
                self.reads += 1
                if self.reads >= self.tolerance:
                    self.reads = 0
                    self.luniebox.pause()
                    self.error_text = False
                    time.sleep(0.1)
            else:
                self.reads = 0
                if text != self.error_text and not self.luniebox.play(text):
                    if self.luniebox.get_setting('luniebox', 'error_sound') != 'False':
                        self.error_text = text
                        self.error_sound()
                time.sleep(0.1)

    def signal_handler(self, signal, frame):
        logging.getLogger('luniebox').info(
            "Caught signal {}, exiting...".format(signal))
        luniebox.stop()
        sys.exit(0)

    def set_volume(self, volume):
        volume_p = subprocess.Popen(
            ["amixer", "set", "PCM",  volume + "%"], stdin=None,
            stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, close_fds=True, shell=False, group="pi", user="pi")
        volume_p.wait()

    def beep_sound(self):
        self.play_sound("/home/pi/luniebox/audio/beep.wav",
                        str(self.luniebox.volume))

    def error_sound(self):
        self.play_sound("/home/pi/luniebox/audio/error.wav", str(
            self.luniebox.get_setting('luniebox', 'error_volume', self.luniebox.volume_max)))

    def play_sound(self, path, volume):
        self.set_volume(volume)
        subprocess.Popen(["aplay", path], stdin=None,
                         stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, close_fds=True, shell=False, group="pi", user="pi")
        self.set_volume(100)


if __name__ == "__main__":
    daemon = LunieboxDaemon(luniebox=luniebox)
    signal.signal(signal.SIGINT, daemon.signal_handler)
    signal.signal(signal.SIGTERM, daemon.signal_handler)

    daemon.run()
