#!/usr/bin/env python
from gpiozero import Button
from gpiozero import LED
from subprocess import check_call

#avoid polling 
from signal import pause

# usb nfc reader
import sys
from evdev import InputDevice, ecodes, categorize


# pin mapping 
PIN_BTN_TGL_START_PAUSE = 4
PIN_BTN_VOL_HIGH = 27
PIN_BTN_VOL_LOW = 24 
PIN_BTN_PREV = 13
PIN_BTN_NEXT = 5

LED_TGL_START_PAUSE = 17
LED_VOL_HIGH = 22
LED_VOL_LOW = 25
LED_VOL_PREV = 16
LED_VOL_NEXT = 6

# other constants
VOLUME_START = 15
BTN_START_STOP_SHUTDOWN_HOLD_TIME = 5

	
CODE_MAP_NFC_CARDS = {
    '0008088162': '\"Markus Osterwalder - Bobo Siebenschläfer macht munter weiter\"',
    '0008079048': '\"Die 30 besten Schlaflieder für Kinder - zum Entspannen und Einschlafen\"',
    '0013045752': '\"Winterkinder\"',
    '0008007958': '\"Ritter Rost\"',
    '0008361980': '\"Die 30 besten Spiel- und Bewegungslieder 2\"',
    '0008087971': '\"Die 30 besten neuen Weihnachts- und Winterlieder\"',
    '0008038413': '\"Das singende Känguruh\"',
    '0008055353': '\"Bibi Blocksberg - 086 - Kann Papi hexen\"',
    '0008398035': '\"Bullshit\"',
    '0008056117': 'http://listen.technobase.fm/tunein-aacplus-pls',
    '0013045720': '\"Yakari 29 - kleine Jäger Grosser Grizzly\"',
    '0008097022': 'http://wdr-kiraka-live.icecast.wdr.de/wdr/kiraka/live/mp3/128/stream.mp3',
}


class Jukebox(object):
	def __init__(self):
		# print("sys._getframe().f_code.co_name + " start")	
		
		# define buttons, see https://gpiozero.readthedocs.io/en/stable/api_input.html#button
		self.btnTglStartPause = Button(PIN_BTN_TGL_START_PAUSE, pull_up=True, hold_time=BTN_START_STOP_SHUTDOWN_HOLD_TIME) # , bounce_time=0.1 ?
		self.btnVolHigh = Button(PIN_BTN_VOL_HIGH, pull_up=True) # , bounce_time=0.1 ?
		self.btnVolLow = Button(PIN_BTN_VOL_LOW, pull_up=True) # , bounce_time=0.1 ?
		self.btnPrev = Button(PIN_BTN_PREV, pull_up=True) # , bounce_time=0.1 ?
		self.btnNext = Button(PIN_BTN_NEXT, pull_up=True) # , bounce_time=0.1 ?
		
		# connect buttons with functions
		self.btnTglStartPause.when_pressed = self.onBtnTglStartPausePressed
		self.btnTglStartPause.when_held = self.onBtnTglStartPauseLongPressed
		self.btnVolHigh.when_pressed = self.onBtnVolHighPressed
		self.btnVolLow.when_pressed = self.onBtnVolLowPressed
		self.btnPrev.when_pressed = self.onBtnPrevPressed
		self.btnNext.when_pressed = self.onBtnNextPressed

		# define LEDs
		self.ledTglStartPause = LED(LED_TGL_START_PAUSE) 
		self.ledVolHigh = LED(LED_VOL_HIGH) 
		self.ledVolLow = LED(LED_VOL_LOW) 
		self.ledPrev = LED(LED_VOL_PREV) 
		self.ledNext = LED(LED_VOL_NEXT) 
		
		# connect LEDs with button state
		self.ledTglStartPause.source = self.btnTglStartPause.values
		self.ledVolHigh.source = self.btnVolHigh.values
		self.ledVolLow.source = self.btnVolLow.values
		self.ledPrev.source = self.btnPrev.values
		self.ledNext.source = self.btnNext.values
		
		
		# play startup sound 
		play("Startup_crop.mp3")


		
	def __del__(self):
		# print(sys._getframe().f_code.co_name + " start")	
		
		# close buttons
		self.btnTglStartPause.close
		self.btnVolHigh.close
		self.btnVolLow.close
		self.btnPrev.close
		self.btnNext.close
		
		# close leds
		self.ledTglStartPause.close
		self.ledVolHigh.close
		self.ledVolLow.close
		self.ledPrev.close
		self.ledNext.close
		
		
	def onBtnTglStartPausePressed(self):
		print(sys._getframe().f_code.co_name + " start!")	
		check_call("mpc toggle", shell=True)

	def onBtnTglStartPauseLongPressed(self):
		print(sys._getframe().f_code.co_name + " start!")	
		check_call("sudo shutdown -h now", shell=True)	

		
	def onBtnVolLowPressed(self):
		print(sys._getframe().f_code.co_name + " start!")	
		check_call("mpc volume -5", shell=True)


	def onBtnVolHighPressed(self):
		print(sys._getframe().f_code.co_name + " start!")	
		check_call("mpc volume +5", shell=True)

		
	def onBtnPrevPressed(self):
		print(sys._getframe().f_code.co_name + " start!")	
		check_call("mpc prev", shell=True)
		
		
	def onBtnNextPressed(self):
		print(sys._getframe().f_code.co_name + " start!")	
		check_call("mpc next", shell=True)

		
# from https://khanhicetea.com/post/read_input_from_usb_keyboard_in_linux/
CODE_MAP_CHAR = {
    'KEY_MINUS': "-",
    'KEY_SPACE': " ",    
    'KEY_U': "U",
    'KEY_W': "W",
    'KEY_BACKSLASH': "\\",
    'KEY_GRAVE': "`",
    'KEY_NUMERIC_STAR': "*",
    'KEY_NUMERIC_3': "3",
    'KEY_NUMERIC_2': "2",
    'KEY_NUMERIC_5': "5",
    'KEY_NUMERIC_4': "4",
    'KEY_NUMERIC_7': "7",
    'KEY_NUMERIC_6': "6",
    'KEY_NUMERIC_9': "9",
    'KEY_NUMERIC_8': "8",
    'KEY_NUMERIC_1': "1",
    'KEY_NUMERIC_0': "0",
    'KEY_E': "E",
    'KEY_D': "D",
    'KEY_G': "G",
    'KEY_F': "F",
    'KEY_A': "A",
    'KEY_C': "C",
    'KEY_B': "B",
    'KEY_M': "M",
    'KEY_L': "L",
    'KEY_O': "O",
    'KEY_N': "N",
    'KEY_I': "I",
    'KEY_H': "H",
    'KEY_K': "K",
    'KEY_J': "J",
    'KEY_Q': "Q",
    'KEY_P': "P",
    'KEY_S': "S",
    'KEY_X': "X",
    'KEY_Z': "Z",
    'KEY_KP4': "4",
    'KEY_KP5': "5",
    'KEY_KP6': "6",
    'KEY_KP7': "7",
    'KEY_KP0': "0",
    'KEY_KP1': "1",
    'KEY_KP2': "2",
    'KEY_KP3': "3",
    'KEY_KP8': "8",
    'KEY_KP9': "9",
    'KEY_5': "5",
    'KEY_4': "4",
    'KEY_7': "7",
    'KEY_6': "6",
    'KEY_1': "1",
    'KEY_0': "0",
    'KEY_3': "3",
    'KEY_2': "2",
    'KEY_9': "9",
    'KEY_8': "8",
    'KEY_LEFTBRACE': "[",
    'KEY_RIGHTBRACE': "]",    
    'KEY_COMMA': ",",
    'KEY_EQUAL': "=",    
    'KEY_SEMICOLON': ";",
    'KEY_APOSTROPHE': "'",
    'KEY_T': "T",
    'KEY_V': "V",
    'KEY_R': "R",
    'KEY_Y': "Y",
    'KEY_TAB': "\t",
    'KEY_DOT': ".",
    'KEY_SLASH': "/",
}

# from https://khanhicetea.com/post/read_input_from_usb_keyboard_in_linux/
def parse_key_to_char(val):
    return CODE_MAP_CHAR[val] if val in CODE_MAP_CHAR else ""

def play(playlist):
	print(sys._getframe().f_code.co_name + " start!")	
	check_call("mpc clear", shell=True)
	check_call("mpc add " + playlist, shell=True)
	check_call("mpc volume " + str(VOLUME_START) , shell=True)
	check_call("mpc play", shell=True)



def parse_nfcCode_toPlaylists(nfcCode):
	print(sys._getframe().f_code.co_name + "(" + nfcCode + ") start!")	
	if (nfcCode in CODE_MAP_NFC_CARDS) :
		playlist = CODE_MAP_NFC_CARDS[nfcCode]
	else:
		print("NFC code " + nfcCode + " is unknown!")
		return
	
	play(playlist)
	print(sys._getframe().f_code.co_name + "(" + nfcCode + ") end!")	


def readNfc():
	# from https://khanhicetea.com/post/read_input_from_usb_keyboard_in_linux/
	device = InputDevice("/dev/input/event0")   # see ls -la /dev/input/
	device.grab()	 # request exclusive access to device

	data = ""
	for event in device.read_loop():
		if event.type == ecodes.EV_KEY:
			e = categorize(event)
			if e.keystate == e.key_up:
				if e.keycode == "KEY_ENTER":
					# sys.stdout.write(data+ '\n')
					# sys.stdout.flush()
					parse_nfcCode_toPlaylists(data)
					data = ""
				else:
					data += parse_key_to_char(e.keycode)
	
	   
if __name__ == '__main__':
	print("Jukebox script start")
	try:
		jb = Jukebox()
		
		readNfc()
		print("Vor pause()!")	
		pause()
		

	except KeyboardInterrupt:
		print("Keyboard Interrupt ")	
		pass
	finally:
		print("finally...")
		del(jb)

print("Jukebox script terminated")