# Path: federation/entities/diaspora/entities.py
# class DiasporaComment(DiasporaRelayableMixin, Comment):
#     """Diaspora comment."""
#     _tag_name = "comment"
# 
#     def to_xml(self):
#         element = etree.Element(self._tag_name)
#         properties = [
#             {"guid": self.guid},
#             {"parent_guid": self.root_target_guid or self.target_guid},
#             {"thread_parent_guid": self.target_guid},
#             {"author_signature": self.signature},
#             {"parent_author_signature": self.parent_signature},
#             {"text": self.raw_content},
#             {"author": self.handle},
#             {"created_at": format_dt(self.created_at)},
#         ]
#         if self.id and self.id.startswith("http"):
#             properties.append({
#                 "activitypub_id": self.id,
#             })
#         struct_to_xml(element, properties)
#         return element
# 
# class DiasporaLike(DiasporaRelayableMixin, Reaction):
#     """Diaspora like."""
#     _tag_name = "like"
#     reaction = "like"
# 
#     def to_xml(self):
#         """Convert to XML message."""
#         element = etree.Element(self._tag_name)
#         struct_to_xml(element, [
#             {"parent_type": "Post"},
#             {"guid": self.guid},
#             {"parent_guid": self.target_guid},
#             {"author_signature": self.signature},
#             {"parent_author_signature": self.parent_signature},
#             {"positive": "true"},
#             {"author": self.handle},
#         ])
#         return element
# 
# class DiasporaRetraction(DiasporaEntityMixin, Retraction):
#     """Diaspora Retraction."""
#     _tag_name = "retraction"
#     mapped = {
#         "Like": "Reaction",
#         "Photo": "Image",
#         "Person": "Profile",
#     }
# 
#     def to_xml(self):
#         """Convert to XML message."""
#         element = etree.Element(self._tag_name)
#         struct_to_xml(element, [
#             {"author": self.handle},
#             {"target_guid": self.target_guid},
#             {"target_type": DiasporaRetraction.entity_type_to_remote(self.entity_type)},
#         ])
#         return element
# 
#     @staticmethod
#     def entity_type_from_remote(value):
#         """Convert entity type between Diaspora names and our Entity names."""
#         if value in DiasporaRetraction.mapped:
#             return DiasporaRetraction.mapped[value]
#         return value
# 
#     @staticmethod
#     def entity_type_to_remote(value):
#         """Convert entity type between our Entity names and Diaspora names."""
#         if value in DiasporaRetraction.mapped.values():
#             values = list(DiasporaRetraction.mapped.values())
#             index = values.index(value)
#             return list(DiasporaRetraction.mapped.keys())[index]
#         return value
# 
# Path: federation/entities/diaspora/mappers.py
# def message_to_objects(
#         message: str, sender: str, sender_key_fetcher:Callable[[str], str]=None, user: UserType =None,
# ) -> List:
#     """Takes in a message extracted by a protocol and maps it to entities.
# 
#     :param message: XML payload
#     :type message: str
#     :param sender: Payload sender id
#     :type message: str
#     :param sender_key_fetcher: Function to fetch sender public key. If not given, key will always be fetched
#         over network. The function should take sender handle as the only parameter.
#     :param user: Optional receiving user object. If given, should have a `handle`.
#     :returns: list of entities
#     """
#     doc = etree.fromstring(message)
#     if doc.tag in TAGS:
#         return element_to_objects(doc, sender, sender_key_fetcher, user)
#     return []
# 
# Path: federation/exceptions.py
# class SignatureVerificationError(Exception):
#     """Authenticity of the signature could not be verified given the key."""
#     pass
# 
# Path: federation/tests/fixtures/keys.py
# def get_dummy_private_key():
#     return RSA.importKey(PRIVATE_KEY)


from unittest.mock import patch, Mock
from lxml import etree
from federation.entities.diaspora.entities import DiasporaComment, DiasporaLike, DiasporaRetraction
from federation.entities.diaspora.mappers import message_to_objects
from federation.exceptions import SignatureVerificationError
from federation.tests.fixtures.keys import get_dummy_private_key
from federation.tests.fixtures.payloads import DIASPORA_POST_COMMENT
import pytest

class TestEntitiesExtractMentions:
    def test_extract_mentions__empty_set_if_no_mentions(self, diasporacomment):
        diasporacomment.extract_mentions()
        assert diasporacomment._mentions == set()

    def test_extract_mentions__set_contains_mentioned_handles(self, diasporapost):
        diasporapost.raw_content = 'yeye @{Jason Robinson 🐍🍻; jaywink@jasonrobinson.me} foobar ' \
                                   '@{bar; foo@example.com}'
        diasporapost.extract_mentions()
        assert diasporapost._mentions == {
            'jaywink@jasonrobinson.me',
            'foo@example.com',
        }

    def test_extract_mentions__set_contains_mentioned_handles__without_display_name(self, diasporapost):
        diasporapost.raw_content = 'yeye @{jaywink@jasonrobinson.me} foobar ' \
                                   '@{bar; foo@example.com}'
        diasporapost.extract_mentions()
        assert diasporapost._mentions == {
            'jaywink@jasonrobinson.me',
            'foo@example.com',
        }


class TestDiasporaRetractionEntityConverters:
    def test_entity_type_from_remote(self):
        assert DiasporaRetraction.entity_type_from_remote("Post") == "Post"
        assert DiasporaRetraction.entity_type_from_remote("Like") == "Reaction"
        assert DiasporaRetraction.entity_type_from_remote("Photo") == "Image"

# Path: federation/entities/diaspora/entities.py
# class DiasporaComment(DiasporaRelayableMixin, Comment):
#     """Diaspora comment."""
#     _tag_name = "comment"
# 
#     def to_xml(self):
#         element = etree.Element(self._tag_name)
#         properties = [
#             {"guid": self.guid},
#             {"parent_guid": self.root_target_guid or self.target_guid},
#             {"thread_parent_guid": self.target_guid},
#             {"author_signature": self.signature},
#             {"parent_author_signature": self.parent_signature},
#             {"text": self.raw_content},
#             {"author": self.handle},
#             {"created_at": format_dt(self.created_at)},
#         ]
#         if self.id and self.id.startswith("http"):
#             properties.append({
#                 "activitypub_id": self.id,
#             })
#         struct_to_xml(element, properties)
#         return element
# 
# class DiasporaLike(DiasporaRelayableMixin, Reaction):
#     """Diaspora like."""
#     _tag_name = "like"
#     reaction = "like"
# 
#     def to_xml(self):
#         """Convert to XML message."""
#         element = etree.Element(self._tag_name)
#         struct_to_xml(element, [
#             {"parent_type": "Post"},
#             {"guid": self.guid},
#             {"parent_guid": self.target_guid},
#             {"author_signature": self.signature},
#             {"parent_author_signature": self.parent_signature},
#             {"positive": "true"},
#             {"author": self.handle},
#         ])
#         return element
# 
# class DiasporaRetraction(DiasporaEntityMixin, Retraction):
#     """Diaspora Retraction."""
#     _tag_name = "retraction"
#     mapped = {
#         "Like": "Reaction",
#         "Photo": "Image",
#         "Person": "Profile",
#     }
# 
#     def to_xml(self):
#         """Convert to XML message."""
#         element = etree.Element(self._tag_name)
#         struct_to_xml(element, [
#             {"author": self.handle},
#             {"target_guid": self.target_guid},
#             {"target_type": DiasporaRetraction.entity_type_to_remote(self.entity_type)},
#         ])
#         return element
# 
#     @staticmethod
#     def entity_type_from_remote(value):
#         """Convert entity type between Diaspora names and our Entity names."""
#         if value in DiasporaRetraction.mapped:
#             return DiasporaRetraction.mapped[value]
#         return value
# 
#     @staticmethod
#     def entity_type_to_remote(value):
#         """Convert entity type between our Entity names and Diaspora names."""
#         if value in DiasporaRetraction.mapped.values():
#             values = list(DiasporaRetraction.mapped.values())
#             index = values.index(value)
#             return list(DiasporaRetraction.mapped.keys())[index]
#         return value
# 
# Path: federation/entities/diaspora/mappers.py
# def message_to_objects(
#         message: str, sender: str, sender_key_fetcher:Callable[[str], str]=None, user: UserType =None,
# ) -> List:
#     """Takes in a message extracted by a protocol and maps it to entities.
# 
#     :param message: XML payload
#     :type message: str
#     :param sender: Payload sender id
#     :type message: str
#     :param sender_key_fetcher: Function to fetch sender public key. If not given, key will always be fetched
#         over network. The function should take sender handle as the only parameter.
#     :param user: Optional receiving user object. If given, should have a `handle`.
#     :returns: list of entities
#     """
#     doc = etree.fromstring(message)
#     if doc.tag in TAGS:
#         return element_to_objects(doc, sender, sender_key_fetcher, user)
#     return []
# 
# Path: federation/exceptions.py
# class SignatureVerificationError(Exception):
#     """Authenticity of the signature could not be verified given the key."""
#     pass
# 
# Path: federation/tests/fixtures/keys.py
# def get_dummy_private_key():
#     return RSA.importKey(PRIVATE_KEY)


# Path: federation/tests/entities/diaspora/test_entities.py
from unittest.mock import patch, Mock
from lxml import etree
from federation.entities.diaspora.entities import DiasporaComment, DiasporaLike, DiasporaRetraction
from federation.entities.diaspora.mappers import message_to_objects
from federation.exceptions import SignatureVerificationError
from federation.tests.fixtures.keys import get_dummy_private_key
from federation.tests.fixtures.payloads import DIASPORA_POST_COMMENT
import pytest


class TestEntitiesExtractMentions:
    def test_extract_mentions__empty_set_if_no_mentions(self, diasporacomment):
        diasporacomment.extract_mentions()
        assert diasporacomment._mentions == set()

    def test_extract_mentions__set_contains_mentioned_handles(self, diasporapost):
        diasporapost.raw_content = 'yeye @{Jason Robinson 🐍🍻; jaywink@jasonrobinson.me} foobar ' \
                                   '@{bar; foo@example.com}'
        diasporapost.extract_mentions()
        assert diasporapost._mentions == {
            'jaywink@jasonrobinson.me',
            'foo@example.com',
        }

    def test_extract_mentions__set_contains_mentioned_handles__without_display_name(self, diasporapost):
        diasporapost.raw_content = 'yeye @{jaywink@jasonrobinson.me} foobar ' \
                                   '@{bar; foo@example.com}'
        diasporapost.extract_mentions()
        assert diasporapost._mentions == {
            'jaywink@jasonrobinson.me',
            'foo@example.com',
        }


class TestDiasporaRetractionEntityConverters:
    def test_entity_type_from_remote(self):
        assert DiasporaRetraction.entity_type_from_remote("Post") == "Post"
        assert DiasporaRetraction.entity_type_from_remote("Like") == "Reaction"
        assert DiasporaRetraction.entity_type_from_remote("Photo") == "Image"

        assert DiasporaRetraction.entity_type_from_remote("Comment") == "Comment"