#!./bin/python3

import os
import sys
import threading
import time
import traceback
from typing import Dict

import pygame # type: ignore
import tornado.ioloop, tornado.web
import asyncio
from display import Display
import menu
import handler

try:
    import RPi.GPIO as GPIO # Support for Raspberry PI GPIO input
except:
    import mock_rpi_gpio as GPIO

class Musikautomat:

    def __init__(self, pydsp, config: Dict):

        # Initialise state objects

        self._autostart = config.get("autostart")
        self._pydsp = pydsp
        self._display = Display(config, self._pydsp)
        self._menu = menu.Menu(config, self._display)
        self._dx = config.get("dimx", 128)

        GPIO.setmode(GPIO.BOARD) # Use physical pin numbering
        GPIO.setwarnings(False) # Disable warnings
        GPIO.setup(3, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
        GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
        GPIO.setup(7, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_UP)

    def runDisplay(self):
        '''
        Run event loop for display and buttons.
        '''
        clk = pygame.time.Clock()
        gpio_event_timer = 0

        #if self._autostart:
        #    self.eventRight()
        #    self.eventRight()

        while True:
            clk.tick(10) # We only need 10 FPS

            if gpio_event_timer > 1:
                if GPIO.input(3) == 0: # Up
                    gpio_event_timer=0
                    self.eventUp()
                elif GPIO.input(5) == 0: # LEFT
                    gpio_event_timer=0
                    self.eventLeft()
                elif GPIO.input(7) == 0: # RIGHT
                    gpio_event_timer=0
                    self.eventRight()
                elif GPIO.input(11) == 0: # DOWN
                    gpio_event_timer=0
                    self.eventDown()
            else:
                gpio_event_timer+=1

            try:
                for event in pygame.event.get():

                    # Handle exit event

                    if event.type == pygame.QUIT:
                        pygame.quit()
                        sys.exit()

                    # Handle key events

                    if event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_UP:
                            self.eventUp()
                        elif event.key == pygame.K_LEFT:
                            self.eventLeft()
                        elif event.key == pygame.K_RIGHT:
                            self.eventRight()
                        elif event.key == pygame.K_DOWN:
                            self.eventDown()

            except Exception as e:

                # Display error
                traceback.print_exc()

                self._pydsp.fill((0,0,0))
                font = pygame.font.Font('freesansbold.ttf', 12)

                s = str(e)
                n = int(self._dx / 6)

                for i, start in enumerate(range(0, len(s), n)):
                    text = font.render(s[start:start+n], True, (255, 0, 0) , (0, 0, 0))
                    self._pydsp.blit(text, (0, i * 12))

                self._eventSink = self._display

            pygame.display.update()

    def eventUp(self):
        self._menu.emitEvent(handler.EVENT_UP)

    def eventDown(self):
        self._menu.emitEvent(handler.EVENT_DOWN)

    def eventLeft(self):
        self._menu.emitEvent(handler.EVENT_LEFT)

    def eventRight(self):
        self._menu.emitEvent(handler.EVENT_RIGHT)
