print "Loading mod: spot_indicator v2016-08-29 (http://forum.worldoftanks.eu/index.php?/topic/441147-)"
"""
spot indicator
by Krzysztof_Chodak aka Kodak
"""
import BigWorld, ResMgr, BattleReplay, Math, Vehicle, GUI, math, os, json
from debug_utils import *
from gui.app_loader import g_appLoader
from PlayerEvents import g_playerEvents
from constants import ARENA_PERIOD, ARENA_BONUS_TYPE
from gui import DEPTH_OF_Aim, g_repeatKeyHandlers, GUI_SETTINGS
from gui.battle_control.battle_constants import HIT_INDICATOR_MAX_ON_SCREEN
#from gui.battle_control.controllers.hit_direction_ctrl import IHitIndicator
from gui.Scaleform.Flash import Flash
from game import convertKeyEvent
from gui.battle_control import g_sessionProvider
enemies = {}
config = None
spotEntries = {}
playerVehicleID = None
myEventsAttached = False
toggleKey = 0
toggleStateOn = True
cw_mode = None
hitDirectionCtrl = None

def MYLOGLIVE(message, permanent_log = True, make_red = True):
    from messenger import MessengerEntry
    if message == '':
        return
    if permanent_log:
        LOG_NOTE(message)
    if make_red:
        message = '<font color="#FF0000">' + message + '</font>'
    try:
        MessengerEntry.g_instance.gui.addClientMessage(message)
    except:
        pass


def MYLOG(*args):
    LOG_NOTE(os.path.basename(__file__), *args)


def MYPPRINT(obj):
    import inspect, pprint
    if isinstance(obj, dict) or isinstance(obj, list) or isinstance(obj, tuple):
        pprint.pprint(obj)
    elif hasattr(obj, '__call__'):
        pprint.pprint(inspect.getargspec(obj))
    else:
        pprint.pprint(inspect.getmembers(obj))


def myPe_onArenaPeriodChange(period = ARENA_PERIOD.BATTLE, *args):
    global myEventsAttached
    global playerVehicleID
    global cw_mode
    global hitDirectionCtrl
    if period is ARENA_PERIOD.BATTLE:
        if not config['showInBattleReplay'] and BattleReplay.g_replayCtrl.isPlaying:
            return
        if g_appLoader.getDefBattleApp() is None:
            BigWorld.callback(1, myPe_onArenaPeriodChange)
            return
        player = BigWorld.player()
        arena = player.arena
        vehicles = arena.vehicles
        #hitDirectionCtrl = g_sessionProvider.getHitDirectionCtrl()
        if player.isVehicleAlive:
            playerVehicleID = player.playerVehicleID
            if 'SPG' not in vehicles[playerVehicleID]['vehicleType'].type.tags:
                cw_mode = arena.bonusType in [
                    ARENA_BONUS_TYPE.CLAN,
                    ARENA_BONUS_TYPE.EVENT_BATTLES,
                    ARENA_BONUS_TYPE.GLOBAL_MAP
                ]
                for vehicleID, desc in vehicles.items():
                    enemy = player.team is not desc['team']
                    if enemy:
                        enemies[vehicleID] = True

                if not myEventsAttached:
                    player.onVehicleEnterWorld += myOnVehicleEnterWorld
                    player.onVehicleLeaveWorld += myOnVehicleLeaveWorld
                    arena.onVehicleKilled += myOnVehicleKilled
                    myEventsAttached = True
            else:
                cleanUp()
        else:
            cleanUp()
    elif period is ARENA_PERIOD.AFTERBATTLE:
        cleanUp()
    return


def cleanUp():
    global playerVehicleID
    global myEventsAttached
    playerVehicleID = None
    if myEventsAttached:
        player = BigWorld.player()
        player.onVehicleEnterWorld -= myOnVehicleEnterWorld
        player.onVehicleLeaveWorld -= myOnVehicleLeaveWorld
        if player.arena:
            player.arena.onVehicleKilled -= myOnVehicleKilled
        myEventsAttached = False
    enemies.clear()
    for vehicleID in spotEntries.iterkeys():
        GUI.delRoot(spotEntries[vehicleID].component)

    spotEntries.clear()
    return


def myOnVehicleEnterWorld(vehicle):
    if not vehicle.isAlive():
        return
    else:
        vehicleID = vehicle.id
        if playerVehicleID is not None and (enemies.has_key(vehicleID) or cw_mode and isEligible(vehicleID)):
            angle, distance = cameraAngleAndDistanceTo(vehicle.position)
            if distance < config.get('noIndicatorAboveM', 450):
                spotInd = my_DamageIndicator()
                spotInd.setup(angle, hitDirectionCtrl.getOffset())
                spotInd.active(True)
                spotInd.component.visible = hitDirectionCtrl.isVisible()
                spotInd.call('DamageIndicator.setDamageFlagAndAnimFrame', [distance <= config.get('strongIndicatorBelowM', 100), 0])
                spotEntries[vehicleID] = spotInd
        return


def isEligible(vehicleID):
    player = BigWorld.player()
    arena = player.arena
    desc = arena.vehicles[vehicleID]
    enemy = player.team is not desc['team']
    if enemy:
        enemies[vehicleID] = True
    return enemy


def myOnVehicleLeaveWorld(vehicle):
    vehicleID = vehicle.id
    if spotEntries.has_key(vehicleID):
        GUI.delRoot(spotEntries[vehicleID].component)
        spotEntries.pop(vehicleID)


def myOnVehicleKilled(vehicleID, *args):
    if vehicleID == playerVehicleID:
        cleanUp()
    elif spotEntries.has_key(vehicleID):
        GUI.delRoot(spotEntries[vehicleID].component)
        spotEntries.pop(vehicleID)


def cameraAngleAndDistanceTo(position):
    camera = BigWorld.camera().position
    angle = math.atan2(camera.x - position.x, camera.z - position.z)
    distance = camera.flatDistTo(position)
    return (angle, distance)


class my_DamageIndicator(Flash):
    __FLASH_CLASS = 'WGHitIndicatorFlash'
    __FLASH_MC_NAME = ('damageMC',) #'spot_{0}'
    __FLASH_SIZE = (680, 680)
    TOTAL_FRAMES = 90
    FRAME_RATE = 24    

    def __init__(self):
        #names = tuple(map(lambda i: self.__FLASH_MC_NAME.format(i), xrange(HIT_INDICATOR_MAX_ON_SCREEN)))
        Flash.__init__(self, config['spotIndicatorSWF'], self.__FLASH_CLASS, [self.__FLASH_MC_NAME]) #, (names,))
        self.component.wg_inputKeyMode = 2
        self.component.position.z = DEPTH_OF_Aim
        self.movie.backgroundAlpha = 0.0
        self.component.focus = False
        self.component.moveFocus = False
        self.component.heightMode = 'PIXEL'
        self.component.widthMode = 'PIXEL'

    def setup(self, gYaw, offset):
        self.component.position.x = offset[0]
        self.component.position.y = offset[1]
        for mcName in my_DamageIndicator.__FLASH_MC_NAME:
            self.component.setGlobalYaw(mcName, gYaw)

    
    def __del__(self):
        LOG_DEBUG('SpotIndicator is deleted')

    def destroy(self):
        self.close()

    def getDuration(self):
        return self.TOTAL_FRAMES / float(self.FRAME_RATE)

    def setOffset(self, offset):
        self.component.position.x = offset[0]
        self.component.position.y = offset[1]

    def setVisible(self, flag):
        self.component.visible = flag

    def showHitDirection(self, idx, gYaw, timeLeft, isDamage):
        name = _DAMAGE_INDICATOR_MC_NAME.format(idx)
        self.component.setGlobalYaw(name, gYaw)
        self.component.invoke(name, ('show', [isDamage, timeLeft * _DAMAGE_INDICATOR_FRAME_RATE]))

    def hideHitDirection(self, idx):
        self.component.invoke(_DAMAGE_INDICATOR_MC_NAME.format(idx), ('hide',))


def myHandleRepeatKeyEvent(event):
    global toggleStateOn
    if GUI_SETTINGS.minimapSize:
        if event.key == toggleKey and event.repeatCount == 1:
            if toggleStateOn:
                toggleStateOn = False
                g_playerEvents.onArenaPeriodChange -= myPe_onArenaPeriodChange
                cleanUp()
                MYLOGLIVE(config.get('toggledOffMsg', ''), make_red=False)
            else:
                toggleStateOn = True
                g_playerEvents.onArenaPeriodChange += myPe_onArenaPeriodChange
                if g_appLoader.getDefBattleApp() is not None:
                    myPe_onArenaPeriodChange()
                MYLOGLIVE(config.get('toggledOnMsg', ''), make_red=False)
            config['toggleStateOn'] = toggleStateOn
            with open(conf_file, 'w') as data_file:
                try:
                    json.dump(config, data_file, sort_keys=True, indent=4, separators=(',', ': '))
                except:
                    print 'Error while saving %s: %s' % (conf_file, sys.exc_info()[0])

    return


conf_file = None
res = ResMgr.openSection('../paths.xml')
sb = res['Paths']
vals = sb.values()[0:2]
for vl in vals:
    path = vl.asString + '/scripts/client/gui/mods/'
    if os.path.isdir(path):
        conf_file = path + 'mod_spot_indicator.json'
        if os.path.isfile(conf_file):
            with open(conf_file) as data_file:
                try:
                    config = json.load(data_file)
                except:
                    import sys
                    print 'Error while loading %s: %s' % (conf_file, sys.exc_info()[0])
                finally:
                    break

if config:
    toggleKey = config['toggleKeyCode']
    if toggleKey > 0:
        g_repeatKeyHandlers.add(myHandleRepeatKeyEvent)
        toggleStateOn = config['toggleStateOn']
    if toggleStateOn:
        g_playerEvents.onArenaPeriodChange += myPe_onArenaPeriodChange

def myOnAvatarBecomeNonPlayer(*args):
    cleanUp()


g_playerEvents.onAvatarBecomeNonPlayer += myOnAvatarBecomeNonPlayer