#TO DO
##[DONE]Add timing correction to the client's playing of the song
#Lots of error checking
#a def load():
#Interface with admin menu
#Allow two modes.  Basic karaoke where the user only downloads mp3's from a small list.  And full mode, where the user downloads mp3's from a FULL list
#Also, need to allow error checking for this so that the admin doesn't accidently start playing a song on the full list while in small mode
#perhaps use "karaoke !mode full" ? or "karaoke !mode [modename]"




import es
import karaokeP  #Custom import
#from time import sleep
import gamethread
import timeparse  #Custom import (which might not be needed?)
import os
import time

info = es.AddonInfo()
info['name']        = "Karaoke Mod"
info['version']     = "0.1.6"
info['author']      = "Goose_Is_King"
info['url']         = "http://mgerow.us"
info['description'] = "Sing along with karaoke, dummy!"

gamedir = str(es.ServerVar('eventscripts_gamedir'))

def load():
        #Check to see if the command karaoke exists prior to setting it
        if not es.exists('command', 'karaoke'):
                es.regcmd('karaoke', 'karaoke/karaoke')
        else:
                #Informs the user that karaoke cannot continue because its command is already bound
                es.dbgmsg(0 , 'FATAL ERROR: Something else is using the command named \'karaoke\'')
                es.dbgmsg(0 , 'Maybe the plugin is already loaded?')
        #if not es.exists('command' , 'setupserver'):
        #    es.regcmd('setupserver' , 'karaoke/setupserver')
                
def karaoke():
        #Fetch the first argument in the command 'karaoke'
        song = es.getargv(1)
        #If that argument is !list, we're going to try and list all the songs available
        if song == '!list':
                files = os.listdir(gamedir + '/addons/eventscripts/karaoke')
                for j in range(len(files)):
                        cFile = files.pop(0)
                        #If the file ends with .txt and is not mp3list.txt, it will be listed
                        #NOTE: mp3list.txt is where the user will list all the names of the
                        #mp3 files they want the client to download
                        if cFile.endswith('.txt') and cFile != 'mp3list.txt':
                                #List each song in the console and remove the . and whatever is after it  ex. "song.txt" returns "song"
                                es.dbgmsg(0 , 'LIST SONG: ' + cFile.partition('.')[0])
                #Returns false to end execution of code
                return False
        #There is probabbly a better way to do this... but playing is set as a global
        #variable and is switched to True when a song is currently playing
        #then switched back off when it is not.  This is to prevent accidental
        #(or purposeful... Headbuddy...)  executing of multiple songs at once
        songTXT = song
        if not song.endswith('.txt'):
                songTXT = song.strip('\n') + '.txt'
        if not os.path.exists(gamedir + '/addons/eventscripts/karaoke/' + songTXT.strip('\n')):
                es.dbgmsg(0 , 'Sorry, couldn\'t find that file.  Try again.')
                return True
        global playing
        try:
                if playing:
                        es.dbgmsg(0 , 'KARAOKE: A song is playing right now, are you deef?')
                        return False
                else:
                        es.dbgmsg(0 , 'KARAOKE:  No song currently playing, here we go!')
        except (UnboundLocalError , NameError):
                #Basically, if playing is not yet defined, we'll assume it is False
                es.dbgmsg(0 , 'KARAOKE:  No song currently playing, here we go!')

        #########################################    
        ##### BEGIN THE ACTUAL SONG SECTION ####################################
        #########################################

        #Grab the current userlist so we can play the song to everyone
        userList = es.getUseridList()
        #Allow karaokeP to parse the song into a list of the times, and lyrics
        #It will also extract the mp3 file, song title, and song length
        #It does NOT need to have the .txt on the end of the song
        karaokeP.parse(song)
        songFile = karaokeP.songBin
        times = karaokeP.times
        lyrics = karaokeP.lyrics
        title = karaokeP.songTitle
        songLength = karaokeP.length
        #Set playing to true so that we don't accidently start playing a song
        #while another song is playing
        playing = True
        #Start a gamethread that flips the global variable 'playing' to False after
        #the song is done.  The 10 seconds is to account for the 10 second countdown
        #before the song actually plays
        gamethread.delayed(songLength + 10 , donePlaying)
        #I don't think this actually does anything (precache sound).
        es.precachesound('karaoke/' + songFile)
        es.centermsg('It\'s Karaoke Time!!!')
        #This is where all the gamethread stuff really starts to get complicated
        #Basically, all the messages, all the lines, and all the times are pre arranged and placed in a sort of queue.   All of this stuff sorta has to happen quickly
        #I could probabbly eliminate any time discrepencies by fetching the time here and subtracting the difference from what is shown.
        
        #Anyway, this line simply shows the title of the song to be played 5 seconds after "It's karaoke time!" shows
        gamethread.delayed(5 , es.centermsg , (title.strip('\n')))
        
        #This seems very complicated...  bear with me
        #For every user in the game (yes, it has to re-run for every user.  This could pose a timing problem that I'll need to fix.  Also, that might be a lot
        #of gamethreads to line up
        #Fetch the current time.  We're going to be subtracting any time that passes from here on out from the game threads.
        startTime = time.time()
        for user in userList:
                #Play the sound with volume zero in order to get it loaded in to the client's memory 10 seconds before the song actually plays
                #This prevents the hiccup that generally occurs when the client plays a sound for the first time
                #THANKS TO SuperDave FROM THE FORUMS FOR HELPING ME WITH THIS HICCUP PROBLEM
                es.playsound(user , 'karaoke/' + songFile , 0)
                #Announcer "ATTENTION" sound.  This should hopefully fire at the same time as the "It's karaoke time!" message shows
                if es.getgame() == 'Team Fortress':
                        es.playsound(user , 'vo/announcer_attention.wav' , 1)
                        #Count down time by using gamethreads.  It seems a bit backwards, but it works.
                        #note
                
                        gamethread.delayed(5 - (time.time() - startTime) , es.playsound , (user , 'vo/announcer_begins_5sec.wav' , 1))
                        gamethread.delayed(6 - (time.time() - startTime) , es.playsound , (user , 'vo/announcer_begins_4sec.wav' , 1))
                        gamethread.delayed(7 - (time.time() - startTime) , es.playsound , (user , 'vo/announcer_begins_3sec.wav' , 1))
                        gamethread.delayed(8 - (time.time() - startTime) , es.playsound , (user , 'vo/announcer_begins_2sec.wav' , 1))
                        gamethread.delayed(9 - (time.time() - startTime) , es.playsound , (user , 'vo/announcer_begins_1sec.wav' , 1))
                #Play the song :)
                gamethread.delayed(10 - (time.time() - startTime) , es.playsound , (user , 'karaoke/' + songFile , 1))
        #startTime = time.time()
        #For all the lyrics in the lyrics list, we're going to give them their own gamethread too.  Luckily, this doesn't have to be done for every user
        for i in range(len(lyrics)):
                #Pop the first Lyric and time on the list (Could imporve this part)
                cLyric = lyrics.pop(0)
                cTime = times.pop(0)
        #this seems complicated, but it really isn't.  We simple add a delay of the current lyric time plus 10 (to account for the 10 second opening)
        #then we subtract the difference in time since this thread started.  We use the command es.centermsg with the text in the current lyric and...
        #viola!  Ok, maybe it is a bit complicated.  There might be some optimization needed here.
                gamethread.delayed(cTime + 10 - (time.time() - startTime) , es.centermsg , (cLyric))
                #es.msg(cLyric)
                #es.msg('AFTER FIRST LYRIC')

#Just a function so that we can easily add all the sounds in mp3list.txt to the download table
def addSounds(soundList , soundDir):
        for soundTitle in soundList:
                es.stringtable('downloadables', 'sound/' + soundDir + soundTitle)
                es.dbgmsg(0 , soundTitle + ' added to download list')
 
def es_map_start(event_var):
        es.dbgmsg(0 , 'Starting map change tweaks')
        #every time the map starts, we are going to re-open the mp3list.txt file and add all of its items to the downloadables list
        f = open(gamedir + '/addons/eventscripts/karaoke/mp3list.txt' , 'r')
        soundList = f.readlines()
        f.close()
        #The directory inside of the 'sounds' directory in which we will store the sounds
        soundDir = 'karaoke/'
        addSounds(soundList , soundDir)

#def server(event_var):
#    es.dbgmsg(0 , 'Starting map change tweaks')
#    #every time the map starts, we are going to re-open the mp3list.txt file and add all of its items to the downloadables list
#    f = open('./t/faddons/eventscripts/karaoke/mp3list.txt' , 'r')
#    soundList = f.readlines()
#    f.close()
#    #The directory inside of the 'sounds' directory in which we will store the sounds
#    soundDir = 'karaoke/'
#    addSounds(soundList , soundDir)

#def es_player_validated(event_var):
#    es.dbgmsg(0 , 'Updating stringtable')
#    f = open('tf/addons/eventscripts/karaoke/mp3list.txt' , 'r')
#    soundList = f.readlines()
#    f.close()
#    soundDir = 'karaoke/'
#    addSounds(soundList , soundDir)

#def round_start(event_var):
#    es.dbgmsg(0 , 'Updating stringtable')
#    f = open('tf/addons/eventscripts/karaoke/mp3list.txt' , 'r')
#    soundList = f.readlines()
#    f.close()
#    soundDir = 'karaoke/'
#    addSounds(soundList , soundDir)

#def setupserver():
#    es.dbgmsg(0 , 'Updating stringtable')
#    f = open('tf/addons/eventscripts/karaoke/mp3list.txt' , 'r')
#    soundList = f.readlines()
#    f.close()
#    soundDir = 'karaoke/'
#    addSounds(soundList , soundDir)
        
#This function is sorta a work around to do something with gamethread
#It just sets the global variable "playing" to false so that we can play a new song.
def donePlaying():
        global playing
        playing = False
