#!./bin/python3

import os

import yaml
import pygame # type: ignore
from typing import Dict
import random

# Color constants

BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
WHITE = (255, 255, 255)

class Display:
    '''
    Display object
    '''
    def __init__(self, config, pydsp):

        # Set config values

        self._dx = config.get("dimx", 128) # Drawing dimensions
        self._dy = config.get("dimy", 160)
        self._playlistFile = config.get("playlist", "music.yml") # Playlist data
        self._pydsp = pydsp # Pygame display object
        self._fontsize = config.get("fontsize", 12) # Fontsize to use
        self._drawlines = int(self._dy / 12) - 5 # Max number of drawn lines

        # Set initialisation values

        self._selection_pointer = 0 # Current selected value
        self._line_offset = 0 # Drawing offset in playlist
        self._current_item = None
        self._bgImg = None


    def getPlaylist(self) -> Dict:
        '''
        Return the playlist for this display.
        '''
        return yaml.safe_load(open(self._playlistFile)).get("playlist", [])


    def update(self):
        '''
        Load the data from the given playlist file and draw it according to the current state.
        '''
        self._pydsp.fill((0,0,0))
        playlist = self.getPlaylist()

        # Correct offset and selection pointer

        if self._selection_pointer < 0:
            self._selection_pointer = 0 # Make sure the selection is at least at pos 0
            if self._line_offset > 0: # Move the line offset down if possible
                self._line_offset-=1
        elif self._selection_pointer > self._drawlines: # Make sure sure selection does not exceed list
            self._selection_pointer = self._drawlines # Move the line offset up if possible
            if self._line_offset < len(playlist) - self._drawlines - 1:
                self._line_offset+=1

        # Draw lines

        font = pygame.font.Font('freesansbold.ttf', self._fontsize)
        drawline = 0 # Line currently drawm

        for i, item in enumerate(playlist):

            # Skip lines until we reached the offset

            if i < self._line_offset:
                continue

            # Draw the line

            if drawline == self._selection_pointer:
                text = font.render(item["name"], True, BLACK, GREEN)

                pygame.draw.rect(self._pydsp, BLACK, (0,0,self._dx,50))
                try:
                    self.drawArt(item)
                except Exception as e:
                    print("Error while drawing art:", e)

                self._current_item = item
            else:
                text = font.render(item["name"], True, GREEN, BLACK)

            self._pydsp.blit(text, (0, drawline * self._fontsize+50))

            # Increase number of drawn lines - stop when the maximum is reached

            drawline += 1
            if drawline > self._drawlines:
                break

    def drawArt(self, item):
        '''
        Beautify the display.
        '''
        font = pygame.font.Font('freesansbold.ttf', self._fontsize)

        # Draw a background image

        if self._bgImg is None:
            bg = os.listdir("web/background")
            bg = bg[random.randint(0, len(bg)-1)]
            self._bgImg = pygame.image.load(os.path.join("web/background", bg))
            pygame.transform.scale(self._bgImg, (self._dx, 50))

        self._pydsp.blit(self._bgImg, (0,0), (0, 0, self._dx, 50))

        path = item.get("path")
        title = item.get("name", "")
        artist = item.get("artist", "")

        # Try to extract meta data

        if path is not None:
            pass

        s = title
        if artist != "":
            s = "%s (%s)" % (s, artist)

        text = font.render(s, True, WHITE, BLACK)
        self._pydsp.blit(text, (0, 38))


    def currentItem(self) -> Dict:
        '''
        Return the current selected item.
        '''
        return self._current_item


    def action(self, action: str):
        '''
        Perform an action to this display.
        '''
        if action == "up":
            self._selection_pointer-=1
        elif action == "down":
            self._selection_pointer+=1

        self.update()
