import os
from datetime import datetime

import pytz

from distribution.utils import date_to_rfc2822_string
from test.utils import get_json
from test.test_adaptors.test_clients.test_rss.base import RSSAdapterBaseTestCase
from test.test_adaptors.test_clients.test_rss.utils import (
    FIXTURES_FOLDER,
    NAMESPACES,
)


class EmbeddedSpecificationTestCase(RSSAdapterBaseTestCase):
    ITEM_TEMPLATE = 'feed-embedded-item.rss'

    def test_general_article_tags(self):
        """Check that general xml tags are correctly generated."""
        data = get_json(
            os.path.join(FIXTURES_FOLDER, 'full.json'))[0]

        tree = self._get_xml_tree_from_data(data)

        item_element = tree.find('.//item')
        self.assertIsNotNone(item_element)

        # Check that the title tag contains the same article title value
        title_element = item_element.find('.//title')
        self.assertIsNotNone(title_element)

        self.assertEqual(title_element.text, data['title'])

        # Check that the dc:abstract tag doesn't exists
        abstract_element = item_element.find('.//{}abstract'.format(NAMESPACES['dc']))
        self.assertIsNone(abstract_element)

        # Check that the description tag contains the article abstract info
        description_element = item_element.find('.//description')
        self.assertIsNotNone(description_element)

        self.assertEqual(data['abstract'], description_element.text)

        # Check that mi:dateTimeWritten tag doesn't exists
        dtwritten_element = item_element.find('.//{}dateTimeWritten'.format(NAMESPACES['mi']))
        self.assertIsNone(dtwritten_element)

        # Check that mi:dateTimeWritten tag doesn't exists
        guid_element = item_element.find('.//guid')
        self.assertIsNotNone(guid_element)

        # Check dc:modified tag
        modified_element = item_element.find('.//{}modified'.format(NAMESPACES['dc']))
        self.assertIsNotNone(modified_element)

        last_modified_datetime = datetime.strptime(
            data['last_modified_datetime'], '%Y-%m-%dT%H:%M:%S.%fZ')
        last_modified_datetime = pytz.utc.localize(last_modified_datetime)

        self.assertEqual(
            modified_element.text,
            date_to_rfc2822_string(last_modified_datetime)
        )

        publication_datetime = datetime.strptime(
            data['publication_datetime'], '%Y-%m-%dT%H:%M:%S.%fZ')
        publication_datetime = pytz.utc.localize(publication_datetime)

        # Check pubDate tag
        pub_date_element = item_element.find('.//pubDate')
        self.assertIsNotNone(pub_date_element)

        self.assertEqual(
            pub_date_element.text,
            date_to_rfc2822_string(publication_datetime)
        )

        # Check mi:shortTitle tag doesn't exists
        short_title_element = item_element.find('.//{}shortTitle'.format(NAMESPACES['mi']))
        self.assertIsNone(short_title_element)

    def test_render_article_without_contributors(self):
        """
        Check that dc:creator tag and dc:contributor tags aren't
        created if there are no contributors.
        """
        data = get_json(
            os.path.join(FIXTURES_FOLDER, 'full.json'))[0]
        data['contributors'] = []

        tree = self._get_xml_tree_from_data(data)

        creator_tags = tree.findall('.//{}creator'.format(NAMESPACES['dc']))
        self.assertEqual(len(creator_tags), 0)

        contributor_tags = tree.findall('.//{}contributor'.format(NAMESPACES['dc']))
        self.assertEqual(len(contributor_tags), 0)

    def test_render_article_with_one_contributor(self):
        """
        Check that dc:creator tag is generated with contributor writer
        name from article contributors.
        """
        data = get_json(
            os.path.join(FIXTURES_FOLDER, 'full.json'))[0]

        tree = self._get_xml_tree_from_data(data)

        creator_tags = tree.findall('.//{}creator'.format(NAMESPACES['dc']))
        self.assertEqual(len(creator_tags), 1)

        creator_tag = creator_tags[0]
        self.assertEqual(creator_tag.text, data['contributors'][0]['name'])

        contributor_tags = tree.findall('.//{}contributor'.format(NAMESPACES['dc']))
        self.assertEqual(contributor_tags, [])

    def test_render_article_with_multiple_contributors(self):
        """
        Check that dc:creator tag is generated with contributor writer name
        from article contributors and that there are the same number of
        dc:contributor tags as the rest of the contributors of the article.
        """
        data = get_json(
            os.path.join(FIXTURES_FOLDER, 'full.json'))[0]
        data['contributors'].extend([{
                "name": "Contributor1",
                "order": 0,
                "role": "",
                "role_other": None,
                "taxonomy_id": "",
                "uri": None
            }, {
                "name": "Contributor2",
                "order": 0,
                "role": "",
                "role_other": None,
                "taxonomy_id": "",
                "uri": None
            }])

        tree = self._get_xml_tree_from_data(data)

        creator_tags = tree.findall('.//{}creator'.format(NAMESPACES['dc']))
        self.assertEqual(len(creator_tags), 1)

        creator_tag = creator_tags[0]
        self.assertEqual(creator_tag.text, data['contributors'][0]['name'])

        contributor_tags = tree.findall('.//{}contributor'.format(NAMESPACES['dc']))
        self.assertEqual(len(contributor_tags), 2)

        for index, contributor_tag in enumerate(contributor_tags):
            self.assertEqual(contributor_tag.text, data['contributors'][index+1]['name'])

    def test_render_article_with_gallery(self):
        """
        Check that the content:encode tag contains the information
        of the first image in the gallery within an img html tag.
        """
        data = get_json(os.path.join(FIXTURES_FOLDER, 'image_gallery.json'))[0]
        gallery_content = data['alt_bodies']['structured']['content'][1]['gallery']

        tree = self._get_xml_tree_from_data(data)

        content_encoded_tag = tree.find('.//{}encoded'.format(NAMESPACES['content']))
        self.assertIsNotNone(content_encoded_tag)

        self.assertEqual(
            content_encoded_tag.text.strip(),
            '<img src="{}" alt="{}" />'.format(
                gallery_content[0]['uri'],
                gallery_content[0]['caption']
            )
        )

    def test_render_article_with_image(self):
        """
        Check that the content:encode tag contains the image
        information within an img html tag.
        """
        data = get_json(os.path.join(FIXTURES_FOLDER, 'image.json'))[0]
        image_content = data['alt_bodies']['structured']['content'][0]['image']

        tree = self._get_xml_tree_from_data(data)

        content_encoded_tag = tree.find('.//{}encoded'.format(NAMESPACES['content']))
        self.assertIsNotNone(content_encoded_tag)

        self.assertEqual(
            content_encoded_tag.text.strip(),
            '<img src="{}" alt="{}" />'.format(
                image_content['uri'],
                image_content['caption']
            )
        )

    def test_render_article_with_text(self):
        """
        Check that content:encode tag contains the text inside
        the text component.
        """
        data = get_json(os.path.join(FIXTURES_FOLDER, 'text.json'))[0]
        text_content = data['alt_bodies']['structured']['content'][0]['text']

        tree = self._get_xml_tree_from_data(data)

        content_encoded_tag = tree.find('.//{}encoded'.format(NAMESPACES['content']))
        self.assertIsNotNone(content_encoded_tag)

        self.assertEqual(
            content_encoded_tag.text.strip(),
            text_content
        )

    def test_render_article_without_alt_bodies(self):
        """
        Check that the content:encode tag contains the article body
        if the `alt_bodies` key is not present within the article.
        """
        data = get_json(os.path.join(FIXTURES_FOLDER, 'full.json'))[0]
        del data['alt_bodies']

        tree = self._get_xml_tree_from_data(data)

        content_encoded_tag = tree.find('.//{}encoded'.format(NAMESPACES['content']))
        self.assertIsNotNone(content_encoded_tag)

        self.assertIn(data['body'], content_encoded_tag.text)

    def test_render_article_without_alt_bodies_and_without_body(self):
        """
        Check that the content:encode tag contains the article abstract
        if `alt_bodies` and `body` keys are not present within the article.
        """
        data = get_json(os.path.join(FIXTURES_FOLDER, 'full.json'))[0]
        del data['alt_bodies']
        del data['body']

        tree = self._get_xml_tree_from_data(data)

        content_encoded_tag = tree.find('.//{}encoded'.format(NAMESPACES['content']))
        self.assertIsNotNone(content_encoded_tag)

        self.assertEqual(data['abstract'], content_encoded_tag.text.strip())
