class BattleChatCommandHandler(bw2_provider.ResponseDictHandler,
                               IBattleCommandFactory):
    sessionProvider = dependency.descriptor(IBattleSessionProvider)

    def __init__(self, provider):
        super(BattleChatCommandHandler, self).__init__(provider)
        self.__factory = BattleCommandFactory()
        self.__targetIDs = []

    @property
    def factory(self):
        return self.__factory

    def clear(self):
        self.__factory = None
        self.__targetIDs = []
        super(BattleChatCommandHandler, self).clear()
        return

    def switch(self, scope):
        self.__targetIDs = []
        if scope != MESSENGER_SCOPE.BATTLE:
            return
        else:
            arena = self.sessionProvider.arenaVisitor.getArenaSubscription()
            if arena is not None:
                arena.onVehicleKilled += self.__onVehicleKilled
            return

    def send(self, decorator):
        command = decorator.getCommand()
        if command:
            provider = self.provider()
            success, reqID = provider.doAction(
                command.id, decorator.getProtoData(), True,
                not GUI_SETTINGS.isBattleCmdCoolDownVisible)
            if reqID:
                self.pushRq(reqID, command)
            if success:
                if decorator.isEnemyTarget():
                    self.__targetIDs.append(decorator.getTargetID())
                provider.setActionCoolDown(command.id, command.cooldownPeriod)
        else:
            LOG_ERROR('Battle command is not found', decorator)

    def registerHandlers(self):
        register = self.provider().registerHandler
        for command in BATTLE_CHAT_COMMANDS:
            register(command.id, self.__onCommandReceived)

        super(BattleChatCommandHandler, self).registerHandlers()

    def unregisterHandlers(self):
        unregister = self.provider().unregisterHandler
        for command in BATTLE_CHAT_COMMANDS:
            unregister(command.id, self.__onCommandReceived)

        super(BattleChatCommandHandler, self).unregisterHandlers()

    def createByName(self, name):
        return self.__factory.createByName(name)

    def createSPGAimAreaCommand(self, desiredShotPosition, cellIdx,
                                reloadTime):
        return self.__factory.createSPGAimAreaCommand(desiredShotPosition,
                                                      cellIdx, reloadTime)

    def createSPGAimTargetCommand(self, targetID, reloadTime):
        return self.__factory.createSPGAimTargetCommand(targetID, reloadTime)

    def createByNameTarget(self, name, targetID):
        return self.__factory.createByNameTarget(name, targetID)

    def createByCellIdx(self, cellIdx):
        return self.__factory.createByCellIdx(cellIdx)

    def createByPosition(self, position):
        return self.__factory.createByPosition(position)

    def createByObjectiveIndex(self, idx, isAtk):
        return self.__factory.createByObjectiveIndex(idx, isAtk)

    def createByBaseIndex(self, idx, name, isAtk):
        return self.__factory.createByBaseIndex(idx, name, isAtk)

    def createByGlobalMsgName(self, actionID, baseName=''):
        return self.__factory.createByGlobalMsgName(actionID, baseName)

    def create4Reload(self, isCassetteClip, timeLeft, quantity):
        return self.__factory.create4Reload(isCassetteClip, timeLeft, quantity)

    def _onResponseFailure(self, ids, args):
        command = super(BattleChatCommandHandler,
                        self)._onResponseFailure(ids, args)
        if command:
            error = errors.createBattleCommandError(args, command)
            if error:
                g_messengerEvents.onErrorReceived(error)
            else:
                LOG_WARNING('Error is not resolved on the client', command,
                            args)

    def __onCommandReceived(self, ids, args):
        actionID, _ = ids
        cmd = self.__factory.createByAction(actionID, args)
        if cmd.isIgnored():
            LOG_DEBUG('Chat command is ignored', cmd)
            return
        if cmd.isPrivate() and not (cmd.isReceiver() or cmd.isSender()):
            return
        g_messengerEvents.channels.onCommandReceived(cmd)

    def __onVehicleKilled(self, victimID, *args):
        provider = self.provider()
        if victimID in self.__targetIDs:
            self.__targetIDs.remove(victimID)
            for actionID in self.__factory.getEnemyTargetCommandsIDs():
                provider.clearActionCoolDown(actionID)