from lxml.html import fromstring
from plone import api
from plone.app.testing import setRoles
from plone.app.testing import TEST_USER_ID
from ploneintranet.activitystream.browser.interfaces import (
    IPloneIntranetActivitystreamLayer,
)
from ploneintranet.activitystream.interfaces import ISimplifiedCommentTrail
from ploneintranet.activitystream.testing import (
    PLONEINTRANET_ACTIVITYSTREAM_INTEGRATION_TESTING,
)
from ploneintranet.layout.tests.test_adapters import _video_request_head
from ploneintranet.microblog.interfaces import IMicroblogTool
from ploneintranet.microblog.statusupdate import StatusUpdate
from ploneintranet.testing import dummy_file
from unittest import mock
from zope.component import queryUtility
from zope.interface import alsoProvides

import unittest


class TestViews(unittest.TestCase):
    layer = PLONEINTRANET_ACTIVITYSTREAM_INTEGRATION_TESTING

    def setUp(self):
        self.portal = self.layer["portal"]
        alsoProvides(self.layer["request"], IPloneIntranetActivitystreamLayer)
        self.request = self.layer["request"].clone()
        setRoles(self.portal, TEST_USER_ID, ["Manager", "Member"])
        self.container = queryUtility(IMicroblogTool)

    def _get_su_for_obj(self, obj):
        for key in self.container._content_uuid_mapping.get(obj.UID(), []):
            return self.container._status_mapping.get(key)

    def test_creating_publishing_two_shares(self):
        doc = api.content.create(
            container=self.portal, type="Document", title="My document"
        )
        api.content.transition(doc, to_state="published")
        # We have 2 auto-generated status updates, for creating and publishing
        found = [x for x in self.container.values()]
        self.assertEqual(2, len(found))
        su1, su2 = found
        # Each status update receives a comment
        su1_comment = StatusUpdate("foo", thread_id=su1.id)
        su2_comment = StatusUpdate("bar", thread_id=su2.id)
        self.container.add(su1_comment)
        self.container.add(su2_comment)
        view = api.content.get_view("content-stream.html", doc, self.request.clone())
        # We get 2 shares and a total of 2 comments
        self.assertEqual(2, view.num_shares)
        self.assertEqual(2, view.num_comments)

    def test_creating_publishing_simple_one_share(self):
        # We repeat the content creation and commenting
        doc = api.content.create(
            container=self.portal, type="Document", title="My document"
        )
        api.content.transition(doc, to_state="published")
        found = [x for x in self.container.values()]
        self.assertEqual(2, len(found))
        su1, su2 = found
        su1_comment = StatusUpdate("foo", thread_id=su1.id)
        su2_comment = StatusUpdate("bar", thread_id=su2.id)
        self.container.add(su1_comment)
        self.container.add(su2_comment)
        # We activate the interface for simplified comment trail
        alsoProvides(doc, ISimplifiedCommentTrail)
        view = api.content.get_view("content-stream.html", doc, self.request.clone())
        # New we only get one share / one comment
        self.assertEqual(1, view.num_shares)
        self.assertEqual(1, view.num_comments)

    def test_post_view_for_documents(self):
        # We repeat the content creation and commenting
        obj = api.content.create(
            container=self.portal, type="Document", title="My document"
        )
        su = self._get_su_for_obj(obj)
        view = api.content.get_view("post.html", su, self.request.clone())
        self.assertEqual(view.post_type, "content_update")
        self.assertEqual(view.content_update_type, "document")
        self.assertFalse(view.content_has_leadimage)
        self.assertEqual(view.content_preview_status_css(), "document document-preview")
        self.assertTrue(view.content_has_previews())
        self.assertListEqual(
            view.content_preview_urls(),
            ["http://nohost/plone/my-document/@@render.svg?page=1"],
        )

    def test_post_view_for_images(self):
        # We repeat the content creation and commenting
        obj = api.content.create(container=self.portal, type="Image", title="My image")
        su = self._get_su_for_obj(obj)
        view = api.content.get_view("post.html", su, self.request.clone())
        self.assertEqual(view.post_type, "content_update")
        self.assertEqual(view.content_update_type, "type-image")
        self.assertFalse(view.content_has_leadimage)
        self.assertEqual(
            view.content_preview_status_css(), "type-image document-preview"
        )
        self.assertTrue(view.content_has_previews())
        self.assertListEqual(
            view.content_preview_urls(), ["http://nohost/plone/my-image"]
        )

    def test_post_view_for_files(self):
        # We repeat the content creation and commenting
        obj = api.content.create(container=self.portal, type="File", title="My file")
        su = self._get_su_for_obj(obj)
        view = api.content.get_view("post.html", su, self.request.clone())
        self.assertEqual(view.post_type, "content_update")
        self.assertEqual(view.content_update_type, "document")
        self.assertFalse(view.content_has_leadimage)
        self.assertEqual(
            view.content_preview_status_css(), "document document-preview not-possible"
        )
        self.assertFalse(view.content_has_previews())
        self.assertListEqual(
            view.content_preview_urls(),
            [
                "http://nohost/plone/++theme++ploneintranet.theme/generated/media/logos/plone-intranet-square.svg"  # noqa: E501
            ],
        )

    def test_post_view_for_audio_files(self):
        # We repeat the content creation and commenting
        obj = api.content.create(
            container=self.portal,
            type="File",
            title="My soundbite",
            file=dummy_file("test.mp3"),
        )
        su = self._get_su_for_obj(obj)
        view = api.content.get_view("post.html", su, self.request.clone())
        self.assertEqual(view.post_type, "content_update")
        self.assertEqual(view.content_update_type, "type-audio")
        self.assertFalse(view.content_has_leadimage)
        self.assertEqual(
            view.content_preview_status_css(), "type-audio document-preview"
        )
        self.assertFalse(view.content_has_previews())
        self.assertListEqual(
            view.content_preview_urls(),
            [
                "http://nohost/plone/++theme++ploneintranet.theme/generated/media/logos/plone-intranet-square.svg"  # noqa: E501
            ],
        )
        # Check we have the video in the preview
        self.assertListEqual(
            [el.attrib["src"] for el in fromstring(view()).cssselect("audio source")],
            ["http://nohost/plone/my-soundbite/@@download/file/test.mp3"],
        )

    def test_post_view_for_video_files(self):
        # We repeat the content creation and commenting
        obj = api.content.create(
            container=self.portal,
            type="File",
            title="My video",
            file=dummy_file("test.mp4"),
        )
        su = self._get_su_for_obj(obj)
        view = api.content.get_view("post.html", su, self.request.clone())
        self.assertEqual(view.post_type, "content_update")
        self.assertEqual(view.content_update_type, "type-video")
        self.assertFalse(view.content_has_leadimage)
        self.assertEqual(
            view.content_preview_status_css(), "type-video document-preview"
        )
        self.assertFalse(view.content_has_previews())
        self.assertListEqual(
            view.content_preview_urls(),
            [
                "http://nohost/plone/++theme++ploneintranet.theme/generated/media/logos/plone-intranet-square.svg"  # noqa: E501
            ],
        )
        # Check we have the video in the preview
        self.assertListEqual(
            [el.attrib["src"] for el in fromstring(view()).cssselect("video source")],
            ["http://nohost/plone/my-video/@@download/file/test.mp4"],
        )

    @mock.patch("requests.head", _video_request_head)
    def test_post_view_for_video_links(self):
        # We repeat the content creation and commenting
        obj = api.content.create(
            container=self.portal,
            type="Link",
            title="My image",
            remoteUrl="http://nohost/test.mp4",
        )
        su = self._get_su_for_obj(obj)
        view = api.content.get_view("post.html", su, self.request.clone())
        self.assertEqual(view.post_type, "content_update")
        self.assertEqual(view.content_update_type, "type-video")
        self.assertFalse(view.content_has_leadimage)
        self.assertEqual(
            view.content_preview_status_css(), "type-video document-preview"
        )
        self.assertFalse(view.content_has_previews())
        self.assertListEqual(
            view.content_preview_urls(),
            [
                "http://nohost/plone/++theme++ploneintranet.theme/generated/media/logos/plone-intranet-square.svg"  # noqa: E501
            ],
        )
        # Check we have the video in the preview
        self.assertListEqual(
            [el.attrib["src"] for el in fromstring(view()).cssselect("video source")],
            ["http://nohost/test.mp4"],
        )

    def test_post_view_for_youtube_links(self):
        # We repeat the content creation and commenting
        obj = api.content.create(
            container=self.portal,
            type="Link",
            title="My image",
            remoteUrl="https://youtube.com?v=VIDEOID",
        )
        su = self._get_su_for_obj(obj)
        view = api.content.get_view("post.html", su, self.request.clone())
        self.assertEqual(view.post_type, "content_update")
        self.assertEqual(view.content_update_type, "type-youtube")
        self.assertFalse(view.content_has_leadimage)
        self.assertEqual(
            view.content_preview_status_css(), "type-youtube document-preview"
        )
        self.assertFalse(view.content_has_previews())
        self.assertListEqual(
            view.content_preview_urls(),
            [
                "http://nohost/plone/++theme++ploneintranet.theme/generated/media/logos/plone-intranet-square.svg"  # noqa: E501
            ],
        )
        # Check we have displayed the iframe
        self.assertListEqual(
            [el.attrib["src"] for el in fromstring(view()).cssselect("iframe")],
            ["https://www.youtube-nocookie.com/embed/VIDEOID"],
        )
        # and that this also works with different kind of URL
        obj.remoteUrl = "https://youtu.be/ANOTHERID"
        self.assertListEqual(
            [el.attrib["src"] for el in fromstring(view()).cssselect("iframe")],
            ["https://www.youtube-nocookie.com/embed/ANOTHERID"],
        )
