import bge
import os
import aud
import random
import glob
from DList import DoubleList
from collections import OrderedDict
from tinytag import TinyTag

""" This is the Music Player as a component """
class MusicPlayer(bge.types.KX_PythonComponent):

    args = OrderedDict([])    

    def start(self, args):
        # dictionary
        self.dictionary = bge.logic.globalDict
        
        # get mp3 files from the disk and create a list
        self.directory = bge.logic.expandPath('//Music')
        file_name = self.directory + '\\*.mp3'
        file_list =  glob.glob(file_name)
        
        # use the mp3 list to make a playlist of nodes
        self.playlist = DoubleList()
        for name in file_list:
            self.playlist.append(name)
        
        # previously played list of nodes
        self.alreadyPlayed = DoubleList()
        
        # get a random song from the playlist, 
        # remove it from the playlist
        # add it to the alreadyPlayed list
        # NOTICE: currentNode is a reference to a NODE in a list, if you want to play the song inside the node, use .data
        self.currentNode = self.playlist.get(random.randint(0, self.playlist.getLength()))
        self.nowPlaying = self.currentNode.getData()
        self.playlist.remove(self.currentNode)
        self.alreadyPlayed.append(self.nowPlaying)
        print("Now Playing: " + self.nowPlaying)
        self.setTag()
        self.isPlaying = False

        # create audio devices
        self.device = aud.device()
        self.factory = aud.Factory(self.nowPlaying)
        self.handle = None        
    
    """ Update is called once every frame, and this is where
        any input handling should go
        
        Controller Buttons: 
        Y-Button - Play/Pause
        LB       - Previous Track
        RB       - Next Track
        
        TODO: Keyboard Buttons if these aren't alright
        P        - Play/Pause
        Pad Plus - Next Track
        Pad Minus- Prev Track
    """
    def update(self):
        keyboard = bge.logic.keyboard.events
        up_dict = bge.logic.globalDict
        #print(dictionary)
        pKey = keyboard[bge.events.PKEY]
        pPlus = keyboard[bge.events.PADPLUSKEY]
        pMinus = keyboard[bge.events.PADMINUS]
        lb = up_dict['lBump']
        last_lb = up_dict['last_lBump']
        rb = up_dict['rBump']
        last_rb = up_dict['last_rBump']
        y = up_dict['yBut']
        last_y = up_dict['last_yBut']
        JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED
        

        #Run player on startup
        if up_dict['music_start'] == True:
            if self.isPlaying:
                self.stopMusic()
            else:
                self.playMusic()                 
            up_dict['music_start'] = False               

        # Music controls only during pause/replay
        if (up_dict['npause'] == True or up_dict['playback'] == True) or up_dict['music_start'] == True:
            #stop/play
            if (y == False and last_y == True) or pKey == JUST_ACTIVATED:
                if self.isPlaying:
                    self.stopMusic()
                    up_dict['music_player'] = 0
                else:
                    self.playMusic()
                    up_dict['music_player'] = 1
            # Prev/Next
            if self.isPlaying and self.handle.status:
                if pMinus == JUST_ACTIVATED or (lb == False and last_lb == True):
                    self.prevSong()
                
                if pPlus == JUST_ACTIVATED or (rb == False and last_rb == True):
                    self.nextSong()
        # if song ends, play next song
        if self.isPlaying and not self.handle.status:
            self.nextSong()

    """ get info about song using TinyTag, then print to console """
    def setTag(self):                
        self.currTrackPath = os.path.join(self.directory, self.nowPlaying)
        tag = TinyTag.get(self.currTrackPath)
        self.currArtist = tag.artist
        self.currTrackTitle = tag.title
        self.dictionary['mu_artist'] = self.currArtist
        self.dictionary['mu_title'] = self.currTrackTitle
                
        print('Artist: %s' % self.currArtist, 
                ' Track: %s' % self.currTrackTitle)

    def playMusic(self):
        print('Play Music')
        self.setTag()
        self.handle = self.device.play(self.factory)
        self.isPlaying = True
        
    def stopMusic(self):
        print('Stop Music')
        self.handle.stop()
        self.isPlaying = False
        
    def nextSong(self):
        print('Next Song')
        # stop the current song
        self.handle.stop()
        
        # get a song from the playlist
        self.currentNode = self.playlist.get(random.randint(0, self.playlist.getLength()))
        self.nowPlaying = self.currentNode.getData()
        self.playlist.remove(self.currentNode)
                
        # add the song to the already played list
        self.alreadyPlayed.append(self.nowPlaying)  
        
        # start the song
        self.factory = aud.Factory(self.nowPlaying)
        self.handle = self.device.play(self.factory)
        self.setTag()
        
        # If playlist is empty, re-fill it
        if self.playlist.getLength() == 0:
            file_name = self.directory + '\\*.mp3'
            file_list =  glob.glob(file_name)
            for name in file_list:
                self.playlist.append(name)
        
    """ Note on first call of this method, the current node will be equal to the tail of the already played list, 
        however, it will be a node from a different list. We need to set current node equal to the tail node
        of the already played list so that we can iterate through that list, instead of the other list """
    def prevSong(self):
        print('Prev Song')
        # stop the current song
        self.handle.stop()        
        
        if self.currentNode.getData() == self.alreadyPlayed.getTail().getData():
            self.currentNode = self.alreadyPlayed.getTail()
            
        self.currentNode = self.currentNode.getPrev()
        self.nowPlaying = self.currentNode.getData()
        
        # start the song
        self.factory = aud.Factory(self.nowPlaying)
        self.handle = self.device.play(self.factory)
        self.setTag()