#!./bin/python3

import os

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

# 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.
        '''
        return
        font = pygame.font.Font('freesansbold.ttf', 10)

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

        # Try to extract meta data

        if path is not None and os.path.isfile(path):
            f = eyed3.load(path)
            title = f.tag.title
            artist = f.tag.artist
            album = f.tag.album
            if f.tag.best_release_date:
                date = str(f.tag.best_release_date)

            # Load album art

            for i in f.tag.images:
                with tempfile.TemporaryFile() as f:
                    f.write(i.image_data)
                    f.seek(0)
                    i = pygame.image.load(f)

                i = pygame.transform.scale(i, (50, 50))
                self._pydsp.blit(i, (0,0), (0, 0, self._dx, 50))

                break

        text = font.render(title, True, WHITE, BLACK)
        self._pydsp.blit(text, (50, 0))

        if artist != "":
            text = font.render(artist, True, WHITE, BLACK)
            self._pydsp.blit(text, (50, 10))

        if album != "":
            text = font.render(album, True, WHITE, BLACK)
            self._pydsp.blit(text, (50, 20))

        if date != "":
            text = font.render(date, True, WHITE, BLACK)
            self._pydsp.blit(text, (50, 30))


    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()
