#!/usr/bin/python
from easy_pipes import Monitor, InputEvent
from hardware import LedPanel
import os
import sys
import time
import evdev
import random
import tinytag
import subprocess
from glob import glob
from pprint import pprint, pformat
import logging

logger = logging.getLogger(__name__)

DIR_MEDIA = '/home/mitch/media/'
DIR_KEYS  = DIR_MEDIA + 'keys/'
DIR_MUSIC = DIR_MEDIA + 'music/'
DIR_MESSAGES = DIR_MEDIA + 'messages/'

PURPLE = (0x80, 0x00, 0xff)

KEY_1 =  2
KEY_2 =  3
KEY_3 =  4
KEY_4 =  5
KEY_5 =  6
KEY_6 =  7
KEY_7 =  8
KEY_8 =  9
KEY_9 =  10
KEY_0 =  11
KEY_KPASTERISK = 55
KEY_R = 19

CHAR_BY_KEY = {
    KEY_1: '1',
    KEY_2: '2',
    KEY_3: '3',
    KEY_4: '4',
    KEY_5: '5',
    KEY_6: '6',
    KEY_7: '7',
    KEY_8: '8',
    KEY_9: '9',
    KEY_0: '0',
    KEY_KPASTERISK: '*',
    KEY_R: 'R',
    }

SONG_BY_KEY = {
    KEY_1: 'world_on_fire',
    KEY_2: 'everything',
    }

def get_input_by_name():
    input_by_name = {}
    for d in evdev.list_devices():
        device = evdev.InputDevice(d)
        input_by_name[device.name] = device
    return input_by_name

def say(text, voice='english-us', block=True):
    wav_file = '/tmp/{}.wav'.format(time.time())
    subprocess.run(['espeak', '-v', voice, '-w', wav_file, text])
    p = subprocess.Popen(['aplay', wav_file])
    if block:
        p.wait()
    else:
        return p

def record(filename):
    logger.info("Recording {}.".format(filename))
    p = subprocess.Popen(['arecord', '-f', 'S16_LE', '-r', '44100', filename])
    return p

def play_song(basename):
    filename = DIR_MUSIC + basename + '.wav'
    return play(filename)

def play(filename):
    logger.info("Playing {}.".format(filename))
    return subprocess.Popen(['aplay', filename])

class Dialer(InputEvent):
    def handle_message(self, message):
        ctx = self.ctx
        if message.type == 1 and message.value == 1:
            key = message.code
            char = CHAR_BY_KEY[key]
            logger.info("dialer: {} pressed.".format(char))
            if key in SONG_BY_KEY:
                if ctx.song:
                    ctx.song.terminate()
                ctx.song = play_song(SONG_BY_KEY[key])
            elif key == KEY_4:
                ctx.panel.set_random(a=2).sync()
            elif key == KEY_5:
                say("Ree cord your message now.  Hang up when done.")
                ctx.recording = record('/tmp/recording.wav')
            elif key == KEY_6:
                if ctx.recording:
                    ctx.recording.terminate()
                ctx.song = play('/tmp/recording.wav')
            else:
                say("You dialed {}.".format(char), block=False)

class Hook(InputEvent):
    def handle_message(self, message):
        ctx = self.ctx
        if message.type == 1:
            logger.info("hook: {}".format(message.value))
            if message.value == 0:
                # Picked up.
                ctx.panel.set_all(0, 255, 0, 16).sync()
                pass
            elif message.value == 1:
                ctx.panel.set_all(255, 0, 0, 16).sync()
                # Hung up.
                if ctx.song:
                    ctx.song.terminate()
                if ctx.recording:
                    ctx.recording.terminate()

if __name__ == '__main__':
    logging.basicConfig(style='{', level=logging.DEBUG, format='{asctime}.{msecs:0.0f}Z {levelname} {funcName}: {message}', datefmt='%Y-%m-%d %H:%M:%S')
    logging.getLogger('easy_pipes').setLevel(logging.INFO)

    logger.info("Starting up.")

    # Load input drivers, if necessary.
    input_by_name = get_input_by_name()
    if not ('hook' in input_by_name and 'dialer' in input_by_name):
        logger.warning("Input drivers not loaded. Doing that now.")
        subprocess.run(['drivers'])
        time.sleep(1)
        input_by_name = get_input_by_name()

    try:
        hook = input_by_name['hook']
        dialer = input_by_name['dialer']
    except KeyError as e:
        logger.error("Still can't find a necessary input device: {}".format(e))
        sys.exit(-1)

    logger.info("Available input devices:")
    for name, device in input_by_name.items():
        logger.info("  * {}: {}".format(device.name, device.path))

    panel = LedPanel(
        gpio_device='/dev/gpiochip0',
        dat=5,
        clk=6,
        lenses=9,
        )
    #panel.set_all(r=64, g=0, b=128, a=4).sync()
    panel.set_all(*PURPLE, a=16).sync()

    logger.info("Ready for interaction. Lift receiver and dial away.")
    Monitor(
        Hook(hook.path),
        Dialer(dialer.path),
        context=dict(
            song=None,
            recording=None,
            panel=panel,
            ),
        ).monitor()
