import logging

from ClientHolder import ClientHolder, ClientWrapper
from utils.tools_message import send_message_wait_and_check_content
from utils.tools_reaction import react_message


# noinspection PyProtectedMember,DuplicatedCode
async def add_update_update_delete(client_1: ClientWrapper, client_2: ClientWrapper):
	# send a message to react to
	sent_message, received_message = await send_message_wait_and_check_content(client_1, client_2, "Message to react to")
	contact_2 = await client_2.get_contact_associated_to_another_client(other_client=client_1)

	####
	# Add reaction
	####
	reaction_1, reaction_2 = await react_message(client_1, client_2, sent_message.id, received_message.id, "A")
	assert reaction_1.reaction == reaction_2.reaction == "A"
	assert reaction_1.contact_id == 0
	assert reaction_2.contact_id == contact_2.id

	reaction_1, reaction_2 = await react_message(client_1, client_2, sent_message.id, received_message.id, "B")
	assert reaction_1.reaction == reaction_2.reaction == "B"
	assert reaction_1.contact_id == 0
	assert reaction_2.contact_id == contact_2.id
	reaction_1, reaction_2 = await react_message(client_1, client_2, sent_message.id, received_message.id, "C")
	assert reaction_1.reaction == reaction_2.reaction == "C"
	assert reaction_1.contact_id == 0
	assert reaction_2.contact_id == contact_2.id

	await react_message(client_1, client_2, sent_message.id, received_message.id, "")


# noinspection PyProtectedMember,DuplicatedCode
async def add_delete_add(client_1: ClientWrapper, client_2: ClientWrapper):
	# send a message to react to
	sent_message, received_message = await send_message_wait_and_check_content(client_1, client_2, "Message to react to")
	contact_2 = await client_2.get_contact_associated_to_another_client(other_client=client_1)

	####
	# Add, remove and add again
	####
	reaction_1, reaction_2 = await react_message(client_1, client_2, sent_message.id, received_message.id, "A")
	assert reaction_1.reaction == reaction_2.reaction == "A"
	assert reaction_1.contact_id == 0
	assert reaction_2.contact_id == contact_2.id

	await react_message(client_1, client_2, sent_message.id, received_message.id, "")

	reaction_1, reaction_2 = await react_message(client_1, client_2, sent_message.id, received_message.id, "C")
	assert reaction_1.reaction == reaction_2.reaction == "C"
	assert reaction_1.contact_id == 0
	assert reaction_2.contact_id == contact_2.id


# noinspection PyProtectedMember,DuplicatedCode
async def add_delete_add_delete(client_1: ClientWrapper, client_2: ClientWrapper):
	# send a message to react to
	sent_message, received_message = await send_message_wait_and_check_content(client_1, client_2, "Message to react to")
	contact_2 = await client_2.get_contact_associated_to_another_client(other_client=client_1)

	reaction_1, reaction_2 = await react_message(client_1, client_2, sent_message.id, received_message.id, "🪱")
	assert reaction_1.reaction == reaction_2.reaction == "🪱"
	assert reaction_1.contact_id == 0
	assert reaction_2.contact_id == contact_2.id

	await react_message(client_1, client_2, sent_message.id, received_message.id, "")

	reaction_1, reaction_2 = await react_message(client_1, client_2, sent_message.id, received_message.id, "🦆")
	assert reaction_1.reaction == reaction_2.reaction == "🦆"
	assert reaction_1.contact_id == 0
	assert reaction_2.contact_id == contact_2.id

	await react_message(client_1, client_2, sent_message.id, received_message.id, "")


# noinspection PyProtectedMember,DuplicatedCode
async def add_update_update_update_delete_add(client_1: ClientWrapper, client_2: ClientWrapper):
	# send a message to react to
	sent_message, received_message = await send_message_wait_and_check_content(client_1, client_2, "Message to react to")
	contact_2 = await client_2.get_contact_associated_to_another_client(other_client=client_1)

	reaction_1, reaction_2 = await react_message(client_1, client_2, sent_message.id, received_message.id, "🪱")
	assert reaction_1.reaction == reaction_2.reaction == "🪱"
	assert reaction_1.contact_id == 0
	assert reaction_2.contact_id == contact_2.id

	reaction_1, reaction_2 = await react_message(client_1, client_2, sent_message.id, received_message.id, "🐧")
	assert reaction_1.reaction == reaction_2.reaction == "🐧"
	assert reaction_1.contact_id == 0
	assert reaction_2.contact_id == contact_2.id

	reaction_1, reaction_2 = await react_message(client_1, client_2, sent_message.id, received_message.id, "🐖")
	assert reaction_1.reaction == reaction_2.reaction == "🐖"
	assert reaction_1.contact_id == 0
	assert reaction_2.contact_id == contact_2.id

	reaction_1, reaction_2 = await react_message(client_1, client_2, sent_message.id, received_message.id, "🪿")
	assert reaction_1.reaction == reaction_2.reaction == "🪿"
	assert reaction_1.contact_id == 0
	assert reaction_2.contact_id == contact_2.id

	await react_message(client_1, client_2, sent_message.id, received_message.id, "")

	reaction_1, reaction_2 = await react_message(client_1, client_2, sent_message.id, received_message.id, "🦆")
	assert reaction_1.reaction == reaction_2.reaction == "🦆"
	assert reaction_1.contact_id == 0
	assert reaction_2.contact_id == contact_2.id


async def add_none(client_1: ClientWrapper, client_2: ClientWrapper):
	# send a message to react to
	sent_message, received_message = await send_message_wait_and_check_content(client_1, client_2, "Message to react to")
	contact_2 = await client_2.get_contact_associated_to_another_client(other_client=client_1)

	# add no reaction to a message (do not trigger a notif)
	await sent_message.react(client_1, "")

# noinspection PyUnusedLocal
async def test_reaction(client_holder: ClientHolder, fast_mode):
	for c1, c2 in client_holder.get_one_client_pair_and_reverse():
		logging.info(f"Reaction routine: {c1.identity.id} <-> {c2.identity.id}")
		await add_update_update_delete(c1, c2)
		logging.info(f"add_delete_add: {c1.identity.id} <-> {c2.identity.id}")
		await add_delete_add(c1, c2)
		logging.info(f"add_delete_add_delete: {c1.identity.id} <-> {c2.identity.id}")
		await add_delete_add_delete(c1, c2)
		logging.info(f"add_update_update_update_delete_add: {c1.identity.id} <-> {c2.identity.id}")
		await add_update_update_update_delete_add(c1, c2)
		logging.info(f"add_none: {c1.identity.id} <-> {c2.identity.id}")
		await add_none(c1, c2)
