# Fuck you Disyer. Stealing my fucking paypal. GET FUCKED: toontown.battle.MovieSound
from panda3d.core import Camera, Point3, Vec3
from direct.interval.IntervalGlobal import *
from BattleBase import *
from BattleProps import *
from BattleSounds import *
import BattleParticles
from RewardPanel import *
import MovieCamera
from direct.directnotify import DirectNotifyGlobal
import MovieUtil
import MovieNPCSOS
from toontown.toonbase import ToontownBattleGlobals
notify = DirectNotifyGlobal.directNotify.newCategory('MovieSound')
soundFiles = ('AA_sound_bikehorn.ogg', 'AA_sound_whistle.ogg', 'AA_sound_bugle.ogg', 'AA_sound_aoogah.ogg', 'AA_sound_elephant.ogg', 'SZ_DD_foghorn.ogg', 'AA_sound_Opera_Singer.ogg')
appearSoundFiles = ('MG_tag_1.ogg', 'LB_receive_evidence.ogg', 'm_match_trumpet.ogg', 'TL_step_on_rake.ogg', 'toonbldg_grow.ogg', 'mailbox_full_wobble.ogg', 'mailbox_full_wobble.ogg')
hitSoundFiles = ('AA_sound_Opera_Singer_Cog_Glass.ogg',)
tSound = 2.45
tSuitReact = 2.8
DISTANCE_TO_WALK_BACK = MovieUtil.SUIT_LURE_DISTANCE * 0.75
TIME_TO_WALK_BACK = 0.5
if DISTANCE_TO_WALK_BACK == 0:
    TIME_TO_WALK_BACK = 0
INSTRUMENT_SCALE_MODIFIER = 0.5
BEFORE_STARS = 0.5
AFTER_STARS = 1.75

def doSounds(sounds):
    if len(sounds) == 0:
        return (None, None)
    else:
        npcArrivals, npcDepartures, npcs = MovieNPCSOS.doNPCTeleports(sounds)
        mtrack = Parallel()
        hitCount = 0
        prevLevel = 0
        prevSounds = [[],
         [],
         [],
         [],
         [],
         [],
         []]
        for sound in sounds:
            level = sound['level']
            prevSounds[level].append(sound)
            for target in sound['target']:
                if target['hp'] > 0:
                    hitCount += 1
                    break

        delay = 0.0
        for soundList in prevSounds:
            if len(soundList) > 0:
                mtrack.append(__doSoundsLevel(soundList, delay, hitCount, npcs))
                delay += TOON_SOUND_DELAY

        soundTrack = Sequence(npcArrivals, mtrack, npcDepartures)
        targets = sounds[0]['target']
        camDuration = mtrack.getDuration()
        enterDuration = npcArrivals.getDuration()
        exitDuration = npcDepartures.getDuration()
        camTrack = MovieCamera.chooseSoundShot(sounds, targets, camDuration, enterDuration, exitDuration)
        return (soundTrack, camTrack)


def __getSuitTrack(sound, lastSoundThatHit, delay, hitCount, targets, totalDamage, hpbonus, toon, npcs):
    tracks = Parallel()
    attacks = 0
    uberDelay = 0.0
    isUber = 0
    level = sound['level']
    if level >= ToontownBattleGlobals.UBER_GAG_LEVEL_INDEX:
        uberDelay = 3.0
        isUber = 1
    for target in targets:
        suit = target['suit']
        if totalDamage > 0 and sound == lastSoundThatHit:
            hp = target['hp']
            died = target['died']
            battle = sound['battle']
            kbbonus = target['kbbonus']
            suitTrack = Sequence()
            showDamage = Func(suit.showHpText, -totalDamage, openEnded=0, attackTrack=SOUND_TRACK, attackLevel=level)
            updateHealthBar = Func(suit.updateHealthBar, totalDamage)
            if isUber:
                breakEffect = BattleParticles.createParticleEffect(file='soundBreak')
                breakEffect.setDepthWrite(0)
                breakEffect.setDepthTest(0)
                breakEffect.setTwoSided(1)
                breakEffect.setBin('fixed', 10)
                soundEffect 
= globalBattleSoundCache.getSound(hitSoundFiles[0])
            suitTrack.append(Wait(delay + tSuitReact))
            if isUber:
                delayTime = random.random()
                suitTrack.append(Wait(delayTime + 2.0))
                suitTrack.append(Func(setPosFromOther, breakEffect, suit, Point3(0, 0.0, suit.getHeight() - 1.0)))
                suitTrack.append(Parallel(showDamage, updateHealthBar, SoundInterval(soundEffect, node=suit), __getPartTrack(breakEffect, 0.0,
 1.0, [breakEffect, suit, 0], softStop=-0.5)))
            else:
                suitTrack.append(showDamage)
                suitTrack.append(updateHealthBar)
            if hitCount == 1:
                suitTrack.append(Parallel(ActorInterval(suit, 'squirt-small'), MovieUtil.createSuitStunInterval(suit, 0.5, 1.8)))
            else:
                suitTrack.append(ActorInterval(suit, 'squirt-small'))
            if kbbonus == 0:
                suitTrack.append(__createSuitResetPosTrack(suit, battle))
                suitTrack.append(Func(battle.unlureSuit, suit))
            bonusTrack = None
            if hpbonus > 0:
                bonusTrack = Sequence(Wait(delay + tSuitReact + delay + 0.75 + uberDelay), Func(suit.showHpText, -hpbonus, 1, openEnded=0), Func(suit.updateHealthBar, hpbonus))
            suitTrack.append(Func(suit.loop, 'neutral'))
            if bonusTrack == None:
                tracks.append(suitTrack)
            else:
                tracks.append(Parallel(suitTrack, bonusTrack))
        elif totalDamage <= 0:
            tracks.append(Sequence(Wait(2.9), Func(MovieUtil.indicateMissed, suit, 1.0)))

    return tracks


def __doSoundsLevel(sounds, delay, hitCount, npcs):
    lastSoundThatHit = None
    totalDamage = 0
    for sound in sounds:
        for target in sound['target']:
            if target['hp'] > 0:
                lastSoundThatHit = sound
                totalDamage += target['hp']
                break

    mainTrack = Sequence()
    tracks = Parallel()
    deathTracks = Parallel()
    for sound in sounds:
        toon = sound['toon']
        if 'npc' in sound:
            toon = sound['npc']
        level = sound['level']
        targets = sound['target']
        hpbonus = sound['hpbonus']
        attackMTrack = soundfn_array[sound['level']](sound, delay, toon, targets, level)
        tracks.append(Sequence(Wait(delay), attackMTrack))
        tracks.append(__getSuitTrack(sound, lastSoundThatHit, delay, hitCount, targets, totalDamage, hpbonus, toon, npcs))
        for target in targets:
            battle = sound['battle']
            suit = target['suit']
            died = target['died']
            revived = target['revived']
            if revived:
                deathTracks.append(MovieUtil.createSuitReviveTrack(suit, toon, battle, npcs))
            elif died:
                deathTracks.append(MovieUtil.createSuitDeathTrack(suit, toon, battle, npcs))

    mainTrack.append(tracks)
    mainTrack.append(deathTracks)
    return mainTrack


def __createSuitResetPosTrack(suit, battle):
    resetPos, resetHpr = battle.getActorPosHpr(suit)
    moveDist = Vec3(suit.getPos(battle) - resetPos).length()
    moveDuration = 0.5
    walkTrack = Sequence(Func(suit.setHpr, battle, resetHpr), ActorInterval(suit, 'walk', startTime=1, duration=moveDuration, endTime=0.0001), Func(suit.loop, 'neutral'))
    moveTrack = LerpPosInterval(suit, moveDuration, resetPos, other=battle)
    return Parallel(walkTrack, moveTrack)


def createSuitResetPosTrack(suit, battle):
    return __createSuitResetPosTrack(suit, battle)


def __createToonInterval(sound, delay, toon, operaInstrument = None):
    isNPC = 0
    if sound.get('npc'):
        isNPC = 1
    battle = sound['battle']
    hasLuredSuits = __hasLuredSuits(sound)
    if not isNPC:
        oldPos, oldHpr = battle.getActorPosHpr(toon)
        newPos = Point3(oldPos)
        newPos.setY(newPos.getY() - DISTANCE_TO_WALK_BACK)
    retval = Sequence(Wait(delay))
    if DISTANCE_TO_WALK_BACK and hasLuredSuits and not isNPC:
        retval.append(Parallel(ActorInterval(toon, 'walk', startTime=1, duration=TIME_TO_WALK_BACK, endTime=0.0001), LerpPosInterval(toon, TIME_TO_WALK_BACK, newPos, other=battle)))
    if operaInstrument:
        sprayEffect = BattleParticles.createParticleEffect(file='soundWave')
        sprayEffect.setDepthWrite(0)
        sprayEffect.setDepthTest(0)
        sprayEffect.setTwoSided(1)
        I1 = 2.8
        retval.append(ActorInterval(