import time
from constants import *
from PyQt4 import QtGui
from os.path import exists
from pybass_constants import *

def handle_packets(caller, total, record=True):
    # Record the packet if demos enabled
    if record and caller.parent.demo_recorder:
        caller.parent.demo_recorder.record(total)
        
    for network in total:
        header = network[0]
        if header == 'MS':
            if len(network) < 15:
                print '[warning]', 'malformed/incomplete MS#chat (IC chat) network message was received'
                continue
            
            if isinstance(network[CHATMSG], unicode):
                network[CHATMSG] = decode_ao_str(network[CHATMSG])
            else:
                network[CHATMSG] = decode_ao_str(network[CHATMSG].decode('utf-8'))
                
            caller.MS_Chat.emit(network)
            
        elif header == 'MC':
            music = decode_ao_str(network[1])
            charid = int(network[2])
            t = time.localtime()
            timestamp = "[%d:%.2d] " % (t[3], t[4]) if not caller.parent.demo_playing else ""
            if charid != -1:
                try:
                    name = caller.parent.charlist[charid][0]
                except:
                    name = 'char id %d' % charid
                
                if len(network) > 3 and network[3]:
                    name += " ("+network[3].decode("utf-8")+")"
                caller.IC_Log.emit(timestamp + '%s changed the music to %s' % (name, music))
            else:
                caller.IC_Log.emit(timestamp + 'The music was changed to %s' % music)
            caller.parent.playMusic(music)

        elif header == 'BN':
            caller.newBackground.emit(network[1].lower(), True)
        
        elif header == 'CT':
            name = decode_ao_str(network[1].decode('utf-8'))
            chatmsg = decode_ao_str(network[2].decode('utf-8').replace("\n", "<br />"))
            caller.OOC_Log.emit("<b>%s:</b> %s" % (name, chatmsg))
        
        elif header == 'PV':
            caller.parent.mychar = int(network[3])
            caller.parent.charselect.hide()
            caller.newChar.emit(caller.parent.charlist[caller.parent.mychar][0])
        
        elif header == 'LE':
            del network[0]
            caller.allEvidence.emit([evi.split('&') for evi in network])

        elif header == 'ZZ':
            if caller.parent.modcall:
                audio.freehandle(caller.parent.modcall)
            caller.parent.modcall = audio.loadhandle(0, "mod_call.wav", 0, 0, 0)
            audio.sethandleattr(caller.parent.modcall, BASS_ATTRIB_VOL, caller.parent.soundslider.value() / 100.0)
            audio.playhandle(caller.parent.modcall, False)
            
            if len(network) > 1:
                caller.OOC_Log.emit('<b>[MOD CALL] ' + network[1].replace("\n", "<br />") + '</b>')
            else:
                caller.OOC_Log.emit('<b>[MOD CALL] But there was no extra information. (old server?)</b>')
        elif header == 'CharsCheck':
            del network[0]
            for i in range(len(network)):
                caller.parent.charlist[i][1] = int(network[i])

            caller.charSlots.emit()
        
        elif header == 'RT':
            testimony = network[1]
            wtcefile = AOpath+"sounds/general/sfx-testimony2"
            if caller.parent.wtcesfx:
                audio.freehandle(caller.parent.wtcesfx)

            if testimony == 'judgeruling':
                variant = int(network[2])
                if variant == 0:
                    wtcefile = AOpath+"sounds/general/sfx-notguilty"
                elif variant == 1:
                    wtcefile = AOpath+"sounds/general/sfx-guilty"
            else:
                variant = 0
            caller.parent.wtcesfx = audio.loadhandle(False, wtcefile+".opus" if exists(wtcefile+".opus") else wtcefile+".wav", 0, 0, 0)
            audio.sethandleattr(caller.parent.wtcesfx, BASS_ATTRIB_VOL, caller.parent.soundslider.value() / 100.0)
            if caller.parent.wtcesfx:
                audio.playhandle(caller.parent.wtcesfx, True)
            caller.parent.WTCEsignal.emit(testimony, variant)
        
        elif header == 'HP':
            kind = int(network[1])
            health = int(network[2])
            caller.parent.healthbars.emit(kind, health)
        
        elif header == 'KK':
            reason = network[1]
            caller.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'critical', 'Connection lost', 'You were kicked from the server. (%s)' % reason)
        
        elif header == 'KB':
            reason = network[1]
            caller.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'critical', 'Connection lost', 'You have been banned from the server. (%s)' % reason)

        elif header == 'BB': # message popup (AO 2.9)
            message = network[1]
            caller.parent.emit(QtCore.SIGNAL('showMessage(QString, QString, QString)'), 'information', 'Message from server', message)

        elif header == 'AUTH': # login status (AO 2.9)
            status = int(network[1])
            statusStrings = ["You have logged out", "Wrong password", "Logged in"]
            if status == 1:
                caller.parent.login = True
                caller.parent.playerKick.setDisabled(False)
                caller.parent.playerBan.setDisabled(False)
                caller.parent.ooclogin.setText("Lo&g out")
            elif status == -1:
                caller.parent.login = False
                caller.parent.playerKick.setDisabled(True)
                caller.parent.playerBan.setDisabled(True)
                caller.parent.ooclogin.setText("Lo&gin")
            caller.OOC_Log.emit("<b>%s</b>" % (statusStrings[status+1]))
            
        elif header == "CHECK": #ping
            pingafter = time.time()
            caller.parent.gotPing.emit(int((pingafter - pingbefore)*1000))
        
        elif header == 'DONE':
            caller.showCharSelect.emit()
            
        elif header == 'PR':
            del network[0]
            caller.updatePlayerList.emit(network[0], 0, int(network[1]), "")
            
        elif header == 'PU':
            del network[0]
            caller.updatePlayerList.emit(network[0], 1, int(network[1]), network[2].decode('utf-8'))
        
        elif header == 'ARUP':
            del network[0]
            kind = int(network[0])
            caller.parent.areas[kind] = [network[i] for i in range(1, len(network))]

            # This is much harder than doing it during the handshake because of the way the music list is implemented
            if caller.parent.no_arup:
                caller.parent.no_arup = False
                caller.parent.areas_len = len(caller.parent.areas[kind])
                print '[client]', 'The server has %d areas' % caller.parent.areas_len
                
                if caller.parent.areas_len:
                    for i in range(caller.parent.areas_len):
                        area_key, area_val = caller.parent.musiclist.items()[0]
                        caller.parent.areas[4].append(area_val)
                        
                        areaitem = QtGui.QListWidgetItem()
                        caller.parent.areaitems.addItem(areaitem)
                        
                        for j in range(len(network)):
                            if j != kind:
                                caller.parent.areas[j].append("")
                                
                        # Remove the area from the music list
                        caller.parent.musiclist.popitem(False)
                
                    caller.parent.allMusic()
                
            for i in range(caller.parent.areas_len):
                area_players = caller.parent.areas[0][i]
                area_status = caller.parent.areas[1][i].title()
                area_cm = caller.parent.areas[2][i].decode('utf-8')
                area_locked = caller.parent.areas[3][i].title()
                area_name = caller.parent.areas[4][i].decode('utf-8')
                if area_status == "Casing":
                    caller.parent.areaitems.item(i).setText("%s\n%s | %s\n%s users | %s" % (area_name, area_status, area_cm, area_players, area_locked))
                else:
                    caller.parent.areaitems.item(i).setText("%s\n%s\n%s users | %s" % (area_name, area_status, area_players, area_locked))
                    
                if area_locked == "Locked":
                    caller.parent.areaitems.item(i).setIcon(QtGui.QIcon(AO2XPpath + "icons/" + "lock.png"))
                else:
                    caller.parent.areaitems.item(i).setIcon(QtGui.QIcon(AO2XPpath + "icons/" + "house.png"))
        
        elif header == 'TI':
            del network[0]
            timer_id = int(network[0])
            command = int(network[1])
            time_ms = 0
            if len(network) == 3:
                time_ms = int(network[2])

            caller.timerUpdate.emit(command, timer_id, time_ms)
            
        # For demos
        elif header == 'SC':
            del network[0]
            caller.parent.charlist = [ [char.split('&')[0].decode('utf-8'), 0, "male", True ] for char in network ]