print "Loading mod: research_watchdog v2016-05-25 (http://forum.worldoftanks.eu/index.php?/topic/457788-)"

from debug_utils import LOG_NOTE, LOG_WARNING, LOG_CURRENT_EXCEPTION
from Account import Account
from gui import SystemMessages
from CurrentVehicle import g_currentVehicle
from PlayerEvents import g_playerEvents
from gui.Scaleform.daapi.view.lobby.techtree import dumpers
from gui.Scaleform.daapi.view.lobby.techtree.settings import NODE_STATE
from gui.Scaleform.daapi.view.lobby.techtree.data import ResearchItemsData
from gui.shared import g_itemsCache
from notification import NotificationMVC
from messenger import MessengerEntry
from messenger.formatters import collections_by_type
from messenger.m_constants import SCH_CLIENT_MSG_TYPE
from notification.decorators import MessageDecorator
from notification.settings import NOTIFICATION_STATE
from items import ITEM_TYPE_NAMES
from helpers import getClientLanguage
import time, ResMgr, os, json, sys, BigWorld, codecs

config = {}
last_intCD = None
alerted = {}
lastMsgPerVehicle = {}
itemTypeNames = []

def MYLOGLIVE(message, permanent_log = True, make_red = True):
    if message=="":
        return
    if permanent_log:
        LOG_NOTE(message)
    if make_red:
        message = '<font color="#FF0000">' + message + '</font>'
    try:
        SystemMessages.pushMessage(message, SystemMessages.SM_TYPE.Information)
    except:
        pass

def MYLOG(*args):
    #LOG_NOTE("%s" % time.strftime('%Y-%m-%d %H:%M:%S'), *args)
    pass

def MYPPRINT(obj, name = False):
    import inspect, pprint
    if isinstance(obj, dict) or isinstance(obj, list) or isinstance(obj, tuple):
        if name:
            print(name)
        pprint.pprint(obj, indent=1, width=180)
    elif hasattr(obj, '__call__'):
        pprint.pprint(inspect.getargspec(obj), indent=1, width=180)
    else:
        pprint.pprint(inspect.getmembers(obj), indent=1, width=180)

def _LOG_EXECUTING_TIME(startTime, methodName, deltaTime = 0.1):
    finishTime = time.time()
    if finishTime - startTime > deltaTime:
        MYLOG('Method "%s" takes too much time %s' % (methodName, finishTime - startTime))

def pushMsg(message, msgType, isAlert = False):
    model = NotificationMVC.g_instance.getModel()
    auxData = [msgType.name()]
    clientID = 0
    try:
        formatted, settings = collections_by_type.CLIENT_FORMATTERS.get(SCH_CLIENT_MSG_TYPE.SYS_MSG_TYPE).format(message, auxData)
    except:
        LOG_CURRENT_EXCEPTION()
        return

    if formatted:
        clientID = MessengerEntry.g_instance.protos.BW.serviceChannel._ServiceChannelManager__idGenerator.next()
        if not settings.isAlert:
            settings.isAlert = isAlert
        checkForModel(MessageDecorator(clientID, formatted, settings))
    else: #if IS_DEVELOPMENT:
        LOG_WARNING('Not enough data to format. Action data : ', message)
    #return clientID

handlerApplied = False
messagesQueue = []

def checkForModel(md):
    global handlerApplied
    model = NotificationMVC.g_instance.getModel()
    if model:
        MYLOG("checkForModel - got model")
        if not handlerApplied:
            model.onDisplayStateChanged += displayStateChangeHandler
            handlerApplied = True
        model.addNotification(md)
        messagesQueue.append(md)
        #keepMsgOnTheListForSeconds = config.get("keepMsgOnTheListForSeconds", 10)
        #if keepMsgOnTheListForSeconds > 0:
            #BigWorld.callback(keepMsgOnTheListForSeconds, lambda: model.removeNotification(md.getType(), md.getID()))
    else:
        MYLOG("checkForModel - no model, waiting")
        BigWorld.callback(1, lambda: checkForModel(md))

def displayStateChangeHandler(oldState, newState, data):
    if newState == NOTIFICATION_STATE.LIST:
        model = NotificationMVC.g_instance.getModel()
        for md in messagesQueue:
            model.removeNotification(md.getType(), md.getID())
        del messagesQueue[:]
        
def onCurrentVehicle(*args):
    global last_intCD
    MYLOG("onCurrentVehicle%s" % str(args))
    if last_intCD is None or last_intCD != g_currentVehicle.item.intCD:
        last_intCD = g_currentVehicle.item.intCD
        MYLOG("g_currentVehicle.invID .item.intCD", g_currentVehicle.invID, last_intCD)
        onXpChanged()

def onXpChanged(*args):
    MYLOG("onXpChanged")
    if not (g_currentVehicle and g_currentVehicle.item):
        MYLOG("no g_currentVehicle.item")
        BigWorld.callback(1, onXpChanged)
        return
    intCD = g_currentVehicle.item.intCD
    if g_currentVehicle.item.isFullyElite:
        msg = config.get("warnIfEliteAndNoCrewAcc", "")
        if not g_currentVehicle.item.isXPToTman and msg != "":
            if not alerted.get(intCD, False):
                alerted[intCD] = True
                pushMsg(msg, SystemMessages.SM_TYPE.Warning, config.get("warnUsingAlertBox", False))
        return
    startTime = time.time()
    rid = ResearchItemsData(dumpers.ResearchItemsObjDumper())
    rid.setRootCD(intCD)
    rid.load()
    msg = ""
    msgpart = config.get("msgItem", "%(item)s")
    altmsg = ""
    altmsgpart = config.get("notifyOfLockedModulesMsgItem", "%(xp)s xp left for %(item)s")
    #MYPPRINT(rid._nodes, "rid._nodes")
    if config.get("useFreeXp", True):
        next2unlock = filter(lambda item: NODE_STATE.ENOUGH_XP & item['state'], rid._nodes)
        if next2unlock:
            #MYPPRINT(next2unlock, "next2unlock ENOUGH_XP")
            for item in next2unlock:
                itemid = int(item['id'])
                oitem = g_itemsCache.items.getItemByCD(itemid)
                msg = msg + "\n" + (msgpart % {
                    "item": trunc(oitem.shortUserName),
                    "itemTypeName": itemTypeName(oitem.itemTypeID)
                })
        next2unlock = filter(lambda item: NODE_STATE.NEXT_2_UNLOCK & item['state'], rid._nodes)
        if next2unlock:
            #MYPPRINT(next2unlock, "next2unlock NEXT_2_UNLOCK")
            xp = g_currentVehicle.item.xp
            for item in next2unlock:
                if not xp >= item['unlockProps'].xpCost:
                    itemid = int(item['id'])
                    oitem = g_itemsCache.items.getItemByCD(itemid)
                    xp_left = "{:,}".format(item['unlockProps'].xpCost - xp).replace(',', ' ')
                    altmsg = altmsg + "\n" + (altmsgpart % {
                        "xp": xp_left,
                        "item": trunc(oitem.shortUserName),
                        "itemTypeName": itemTypeName(oitem.itemTypeID)
                    })
    else:
        next2unlock = filter(lambda item: NODE_STATE.NEXT_2_UNLOCK & item['state'], rid._nodes)
        if next2unlock:
            xp = g_currentVehicle.item.xp
            for item in next2unlock:
                itemid = int(item['id'])
                oitem = g_itemsCache.items.getItemByCD(itemid)
                if xp >= item['unlockProps'].xpCost:
                    msg = msg + "\n" + (msgpart % {
                        "item": trunc(oitem.shortUserName),
                        "itemTypeName": itemTypeName(oitem.itemTypeID)
                    })
                else:
                    xp_left = "{:,}".format(item['unlockProps'].xpCost - xp).replace(',', ' ')
                    altmsg = altmsg + "\n" + (altmsgpart % {
                        "xp": xp_left,
                        "item": trunc(oitem.shortUserName),
                        "itemTypeName": itemTypeName(oitem.itemTypeID)
                    })
    if altmsg != "" and config.get("notifyOfLockedModules", True):
        altmsg = config.get("notifyOfLockedModulesMsg", "Item(s) yet to be researched:") + altmsg
        if msg != "":
            msg = msg + "\n\n" + altmsg
        else:
            pushMsgIfChanged(altmsg, intCD)
    if msg != "":
        pushMsgIfChanged(config.get("msg", "Item(s) ready to be researched:") + msg, intCD)
    _LOG_EXECUTING_TIME(startTime, 'onXpChanged')

def pushMsgIfChanged(msg, intCD, msgType = SystemMessages.SM_TYPE.GameGreeting):
    #MYPPRINT(lastMsgPerVehicle, "lastMsgPerVehicle")
    if msg != lastMsgPerVehicle.get(intCD, "") or config.get("supressSameMsg", True)==False:
        lastMsgPerVehicle[intCD] = msg
        pushMsg(msg, msgType)
    
def myOnBattleResultsReceived(isPlayerVehicle, results):
    #MYLOG("myOnBattleResultsReceived")
    #MYLOG(isPlayerVehicle)
    #MYPPRINT(results)
    onXpChanged()

def myOnAvatarBecomeNonPlayer(*args):
    global handlerApplied
    g_currentVehicle.onChanged += onCurrentVehicle
    handlerApplied = False

def trunc(data):
    maxlen = config.get("maxCharsPerItem", 50)
    return (data[:maxlen] + config.get("cutOffSymbol", '..')) if len(data) > maxlen else data

def itemTypeName(itemTypeID):
  try:
    return itemTypeNames[itemTypeID]
  except IndexError:
    return "%d?" % itemTypeID

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_research_watchdog.json'
        if os.path.isfile(conf_file):
            with codecs.open(conf_file, 'r', 'utf-8-sig') as data_file:
                try:
                    config = json.load(data_file)
                    config.update(config.get(getClientLanguage(), config.get("en", {})))
                    itemTypeNames = config.get("itemTypeNames", ITEM_TYPE_NAMES)
                except:
                    import sys
                    print "Error while loading %s: %s" % (conf_file, sys.exc_info()[0])
                finally:
                    break

def connectionManager_onConnected(*args):
    MYLOG("connectionManager_onConnected%s" % str(args))
    g_currentVehicle.onChanged += onCurrentVehicle
    g_playerEvents.onBattleResultsReceived += myOnBattleResultsReceived
    g_playerEvents.onVehicleBecomeElite += onXpChanged
    g_playerEvents.onAvatarBecomeNonPlayer += myOnAvatarBecomeNonPlayer

from ConnectionManager import connectionManager
connectionManager.onConnected += connectionManager_onConnected
