"""
Test the publish code (mostly testing that publishing doesn't result in orphans)
"""
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.tests.test_split_w_old_mongo import SplitWMongoCourseBoostrapper
from xmodule.modulestore.tests.factories import check_mongo_calls


class TestPublish(SplitWMongoCourseBoostrapper):
    """
    Test the publish code (primary causing orphans)
    """
    def _create_course(self):
        """
        Create the course, publish all verticals
        * some detached items
        """
        # There should be 12 inserts and 11 updates (max_sends)
        # Should be 1 to verify course unique, 11 parent fetches,
        # and n per _create_item where n is the size of the course tree non-leaf nodes
        # for inheritance computation (which is 7*4 + sum(1..4) = 38) (max_finds)
        with check_mongo_calls(self.draft_mongo, 70, 27):
            with check_mongo_calls(self.old_mongo, 70, 27):
                super(TestPublish, self)._create_course(split=False)

                self._create_item('chapter', 'Chapter1', {}, {'display_name': 'Chapter 1'}, 'course', 'runid', split=False)
                self._create_item('chapter', 'Chapter2', {}, {'display_name': 'Chapter 2'}, 'course', 'runid', split=False)
                self._create_item('vertical', 'Vert1', {}, {'display_name': 'Vertical 1'}, 'chapter', 'Chapter1', split=False)
                self._create_item('vertical', 'Vert2', {}, {'display_name': 'Vertical 2'}, 'chapter', 'Chapter1', split=False)
                self._create_item('html', 'Html1', "<p>Goodbye</p>", {'display_name': 'Parented Html'}, 'vertical', 'Vert1', split=False)
                self._create_item(
                    'discussion', 'Discussion1',
                    "discussion discussion_category=\"Lecture 1\" discussion_id=\"a08bfd89b2aa40fa81f2c650a9332846\" discussion_target=\"Lecture 1\"/>\n",
                    {
                        "discussion_category": "Lecture 1",
                        "discussion_target": "Lecture 1",
                        "display_name": "Lecture 1 Discussion",
                        "discussion_id": "a08bfd89b2aa40fa81f2c650a9332846"
                    },
                    'vertical', 'Vert1',
                    split=False
                )
                self._create_item('html', 'Html2', "<p>Hellow</p>", {'display_name': 'Hollow Html'}, 'vertical', 'Vert1', split=False)
                self._create_item(
                    'discussion', 'Discussion2',
                    "discussion discussion_category=\"Lecture 2\" discussion_id=\"b08bfd89b2aa40fa81f2c650a9332846\" discussion_target=\"Lecture 2\"/>\n",
                    {
                        "discussion_category": "Lecture 2",
                        "discussion_target": "Lecture 2",
                        "display_name": "Lecture 2 Discussion",
                        "discussion_id": "b08bfd89b2aa40fa81f2c650a9332846"
                    },
                    'vertical', 'Vert2',
                    split=False
                )
                self._create_item('static_tab', 'staticuno', "<p>tab</p>", {'display_name': 'Tab uno'}, None, None, split=False)
                self._create_item('about', 'overview', "<p>overview</p>", {}, None, None, split=False)
                self._create_item('course_info', 'updates', "<ol><li><h2>Sep 22</h2><p>test</p></li></ol>", {}, None, None, split=False)


    def test_publish_draft_delete(self):
        """
        To reproduce a bug (STUD-811) publish a vertical, convert to draft, delete a child, move a child, publish.
        See if deleted and moved children still is connected or exists in db (bug was disconnected but existed)
        """
        location = self.old_course_key.make_usage_key('vertical', name='Vert1')
        item = self.draft_mongo.get_item(location, 2)
        # Vert1 has 3 children; so, publishes 4 nodes which may mean 4 inserts & 1 bulk remove
        # 25-June-2014 find calls are 19. Probably due to inheritance recomputation?
        with check_mongo_calls(self.draft_mongo, 19, 5):
            self.draft_mongo.publish(item.location, self.userid)

        # verify status
        item = self.draft_mongo.get_item(location, 0)
        self.assertFalse(getattr(item, 'is_draft', False), "Item was published. Draft should not exist")
        # however, children are still draft, but I'm not sure that's by design

        # convert back to draft
        self.draft_mongo.convert_to_draft(location, self.userid)
        # both draft and published should exist
        draft_vert = self.draft_mongo.get_item(location, 0)
        self.assertTrue(getattr(draft_vert, 'is_draft', False), "Item was converted to draft but doesn't say so")
        item = self.old_mongo.get_item(location, 0)
        self.assertFalse(getattr(item, 'is_draft', False), "Published item doesn't say so")

        # delete the draft version of the discussion
        location = self.old_course_key.make_usage_key('discussion', name='Discussion1')
        self.draft_mongo.delete_item(location, self.userid)

        draft_vert = self.draft_mongo.get_item(draft_vert.location, 0)
        # remove pointer from draft vertical (still there b/c not refetching vert)
        self.assertNotIn(location, draft_vert.children)
        # move the other child
        other_child_loc = self.old_course_key.make_usage_key('html', name='Html2')
        draft_vert.children.remove(other_child_loc)
        other_vert = self.draft_mongo.get_item(self.old_course_key.make_usage_key('vertical', name='Vert2'), 0)
        other_vert.children.append(other_child_loc)
        self.draft_mongo.update_item(draft_vert, self.userid)
        self.draft_mongo.update_item(other_vert, self.userid)
        # publish
        self.draft_mongo.publish(draft_vert.location, self.userid)
        item = self.old_mongo.get_item(draft_vert.location, 0)
        self.assertNotIn(location, item.children)
        self.assertIsNone(self.draft_mongo.get_parent_location(location))
        with self.assertRaises(ItemNotFoundError):
            self.draft_mongo.get_item(location)
        self.assertNotIn(other_child_loc, item.children)
        self.assertTrue(self.draft_mongo.has_item(other_child_loc), "Oops, lost moved item")
