import asyncio
import datetime
import itertools
import sys

import logs
from jj2 import GameClient
from jj2.connection import Lookup
from jj2.utils import remove_markup


class LoggerBot(GameClient):
    log_id = len(list(logs.PATH.glob(r'chatlog-*.txt')))
    default_streams = (sys.stdout, open(f'../logs/chatlog-{str(log_id).zfill(4)}.txt', 'w+'))

    def __init__(self, *args, streams=(), use_default_streams=True, **kwargs):
        super().__init__(*args, **kwargs)
        self.streams = streams
        if use_default_streams:
            self.streams += self.default_streams

    @staticmethod
    def format_line(connection, *args, sep=' ', dt=True, connection_name=True):
        return sep.join((
            *itertools.compress((
                datetime.datetime.now().strftime('%H:%M:%S').join('[]'),
                connection.name.join('()'),
            ), (dt, connection_name)),
            *args
        ))

    async def log(self, connection, *args, **kwargs):
        line = self.format_line(connection, *args, **kwargs)
        for stream in self.streams:
            print(
                line, **kwargs,
                file=stream
            )
            stream.flush()
        return line

    async def on_join(self, connection, spectate=True):
        await self.log(
            connection,
            f'Joined as {connection.local_players[0].nickname}',
        )
        await asyncio.sleep(1)
        spectate and await self.spectate(connection)

    async def on_game_initiation(self, connection):
        await asyncio.sleep(0.5)
        await self.print_players(connection)

    async def on_disconnect(self, connection, reason):
        await self.log(
            connection,
            f'Disconnected: {reason}',
        )

    async def on_player_roasted(self, connection, killer, victim):
        if killer == connection.me:
            await self.log(
                connection,
                f'you roasted {victim.nickname}'
            )
        else:
            await self.log(
                connection,
                f'{killer.nickname} roasted {victim.nickname}'
            )

    async def on_player_suicide(self, connection, suicide):
        await self.log(
            connection,
            f'{suicide.nickname} ate it'
        )

    async def on_roasted(self, connection, killer):
        await self.log(
            connection,
            f'you got roasted by {killer.nickname}'
        )

    async def on_suicide(self, connection):
        await self.log(
            connection,
            f'you killed yourself'
        )

    async def on_client_join(self, connection, players):
        for player in players:
            await self.log(
                connection,
                player.nickname,
                'joined the game',
            )

    async def on_client_disconnect(self, connection, players, reason=None):
        for player in players:
            await self.log(
                connection,
                player.nickname,
                'left the game' + (f' ({reason})' if reason else ''),
            )

    async def on_server_details(self, connection, server_cache):
        await self.log(
            connection,
            'Current level:',
            server_cache.level.file_name,
        )
        await self.log(
            connection,
            'Game mode:', server_cache.game_mode.pretty,
        )

    async def on_console_message(self, connection, message):
        await self.log(
            connection,
            ('' if message.hide_console else 'Console: ') + message.text,
        )

    async def on_action_message(self, connection, message):
        await self.log(
            connection,
            '*', message.author.nickname, message.text
        )

    async def on_chat_message(self, connection, message):
        text = message.raw_text
        await self.log(
            connection,
            message.author.nickname + ':', text,
        )

    async def on_team_chat_message(self, connection, message):
        text = message.text
        await self.log(
            connection,
            message.author.nickname.join('[]') + ':', text,
        )

    async def on_level_cycle(self, connection, level):
        await self.log(
            connection,
            f'The level has been cycled to {level.file_name}',
        )
        await self.print_players(connection)

    async def print_players(self, connection):
        lines = []
        for player in connection.server_cache.players:
            lines.append(
                f'({player.number_in_list}{"s" if player.is_spectating else "p"}) '
                f'{player.nickname} '
                f'{(player.connection_status.join("()")) if not player.is_host else "(host)"}'
            )

        await self.log(connection, 'Players:', ', '.join(lines))

    async def on_quit(self, connection):
        await self.log(connection, 'Connection has been quitted')


if __name__ == '__main__':
    from scripts import play
    play(connect=[Lookup('Zeal Duels')])

import asyncio
import datetime
import itertools
import sys

import logs
from jj2 import GameClient
from jj2.connection import Lookup
from jj2.utils import remove_markup


class LoggerBot(GameClient):
    log_id = len(list(logs.PATH.glob(r'chatlog-*.txt')))
    default_streams = (sys.stdout, open(f'../logs/chatlog-{str(log_id).zfill(4)}.txt', 'w+'))

    def __init__(self, *args, streams=(), use_default_streams=True, **kwargs):
        super().__init__(*args, **kwargs)
        self.streams = streams
        if use_default_streams:
            self.streams += self.default_streams

    @staticmethod
    def format_line(connection, *args, sep=' ', dt=True, connection_name=True):
        return sep.join((
            *itertools.compress((
                datetime.datetime.now().strftime('%H:%M:%S').join('[]'),
                connection.name.join('()'),
            ), (dt, connection_name)),
            *args
        ))

    async def log(self, connection, *args, **kwargs):
        line = self.format_line(connection, *args, **kwargs)
        for stream in self.streams:
            print(
                line, **kwargs,
                file=stream
            )
            stream.flush()
        return line

    async def on_join(self, connection, spectate=True):
        await self.log(
            connection,
            f'Joined as {connection.local_players[0].nickname}',
        )
        await asyncio.sleep(1)
        spectate and await self.spectate(connection)

    async def on_game_initiation(self, connection):
        await asyncio.sleep(0.5)
        await self.print_players(connection)

    async def on_disconnect(self, connection, reason):
        await self.log(
            connection,
            f'Disconnected: {reason}',
        )

    async def on_player_roasted(self, connection, killer, victim):
        if killer == connection.me:
            await self.log(
                connection,
                f'you roasted {victim.nickname}'
            )
        else:
            await self.log(
                connection,
                f'{killer.nickname} roasted {victim.nickname}'
            )

    async def on_player_suicide(self, connection, suicide):
        await self.log(
            connection,
            f'{suicide.nickname} ate it'
        )

    async def on_roasted(self, connection, killer):
        await self.log(
            connection,
            f'you got roasted by {killer.nickname}'
        )

    async def on_suicide(self, connection):
        await self.log(
            connection,
            f'you killed yourself'
        )

    async def on_client_join(self, connection, players):
        for player in players:
            await self.log(
                connection,
                player.nickname,
                'joined the game',
            )

    async def on_client_disconnect(self, connection, players, reason=None):
        for player in players:
            await self.log(
                connection,
                player.nickname,
                'left the game' + (f' ({reason})' if reason else ''),
            )

    async def on_server_details(self, connection, server_cache):
        await self.log(
            connection,
            'Current level:',
            server_cache.level.file_name,
        )
        await self.log(
            connection,
            'Game mode:', server_cache.game_mode.pretty,
        )

    async def on_console_message(self, connection, message):
        await self.log(
            connection,
            ('' if message.hide_console else 'Console: ') + message.text,
        )

    async def on_action_message(self, connection, message):
        await self.log(
            connection,
            '*', message.author.nickname, message.text
        )

    async def on_chat_message(self, connection, message):
        text = message.raw_text
        await self.log(
            connection,
            message.author.nickname + ':', text,
        )

    async def on_team_chat_message(self, connection, message):
        text = message.text
        await self.log(
            connection,
            message.author.nickname.join('[]') + ':', text,
        )

    async def on_level_cycle(self, connection, level):
        await self.log(
            connection,
            f'The level has been cycled to {level.file_name}',
        )
        await self.print_players(connection)

    async def print_players(self, connection):
        lines = []
        for player in connection.server_cache.players:
            lines.append(
                f'({player.number_in_list}{"s" if player.is_spectating else "p"}) '
                f'{player.nickname} '
                f'{(player.connection_status.join("()")) if not player.is_host else "(host)"}'
            )

        await self.log(connection, 'Players:', ', '.join(lines))

    async def on_quit(self, connection):
        await self.log(connection, 'Connection has been quitted')


if __name__ == '__main__':
    from scripts import play
    play(connect=[Lookup('Zeal Duels')])
