import collections
import datetime
import mock
import pytz
from babel import dates, Locale
from schema import Schema, And, Use, Or
from django.utils import timezone

from osf.modm_compat import Q
from modularodm.exceptions import NoResultsFound
from nose.tools import *  # noqa PEP8 asserts

from framework.auth import Auth
from osf.models import Node, Comment, NotificationDigest, NotificationSubscription, Guid, OSFUser

from website.notifications.tasks import get_users_emails, send_users_email, group_by_node, remove_notifications
from website.notifications import constants
from website.notifications import emails
from website.notifications import utils
from website import mails, settings
from website.project.signals import contributor_removed, node_deleted
from website.util import api_url_for
from website.util import web_url_for

from osf_tests import factories
from tests.base import capture_signals
from tests.base import OsfTestCase, NotificationTestCase


class TestNotificationsModels(OsfTestCase):

    def setUp(self):
        super(TestNotificationsModels, self).setUp()
        # Create project with component
        self.user = factories.UserFactory()
        self.consolidate_auth = Auth(user=self.user)
        self.parent = factories.ProjectFactory(creator=self.user)
        self.node = factories.NodeFactory(creator=self.user, parent=self.parent)

    def test_has_permission_on_children(self):
        non_admin_user = factories.UserFactory()
        parent = factories.ProjectFactory()
        parent.add_contributor(contributor=non_admin_user, permissions=['read'])
        parent.save()

        node = factories.NodeFactory(parent=parent, category='project')
        sub_component = factories.NodeFactory(parent=node)
        sub_component.add_contributor(contributor=non_admin_user)
        sub_component.save()
        sub_component2 = factories.NodeFactory(parent=node)

        assert_true(
            node.has_permission_on_children(non_admin_user, 'read')
        )

    def test_check_user_has_permission_excludes_deleted_components(self):
        non_admin_user = factories.UserFactory()
        parent = factories.ProjectFactory()
        parent.add_contributor(contributor=non_admin_user, permissions=['read'])
        parent.save()

        node = factories.NodeFactory(parent=parent, category='project')
        sub_component = factories.NodeFactory(parent=node)
        sub_component.add_contributor(contributor=non_admin_user)
        sub_component.is_deleted = True
        sub_component.save()
        sub_component2 = factories.NodeFactory(parent=node)

        assert_false(
            node.has_permission_on_children(non_admin_user,'read')
        )

    def test_check_user_does_not_have_permission_on_private_node_child(self):
        non_admin_user = factories.UserFactory()
        parent = factories.ProjectFactory()
        parent.add_contributor(contributor=non_admin_user, permissions=['read'])
        parent.save()
        node = factories.NodeFactory(parent=parent, category='project')
        sub_component = factories.NodeFactory(parent=node)

        assert_false(
            node.has_permission_on_children(non_admin_user,'read')
        )

    def test_check_user_child_node_permissions_false_if_no_children(self):
        non_admin_user = factories.UserFactory()
        parent = factories.ProjectFactory()
        parent.add_contributor(contributor=non_admin_user, permissions=['read'])
        parent.save()
        node = factories.NodeFactory(parent=parent, category='project')

        assert_false(
            node.has_permission_on_children(non_admin_user,'read')
        )

    def test_check_admin_has_permissions_on_private_component(self):
        parent = factories.ProjectFactory()
        node = factories.NodeFactory(parent=parent, category='project')
        sub_component = factories.NodeFactory(parent=node)

        assert_true(
            node.has_permission_on_children(parent.creator,'read')
        )

    def test_check_user_private_node_child_permissions_excludes_pointers(self):
        user = factories.UserFactory()
        parent = factories.ProjectFactory()
        pointed = factories.ProjectFactory(creator=user)
        parent.add_pointer(pointed, Auth(parent.creator))
        parent.save()

        assert_false(
            parent.has_permission_on_children(user,'read')
        )

    def test_new_project_creator_is_subscribed(self):
        user = factories.UserFactory()
        factories.ProjectFactory(creator=user)
        user_subscriptions = list(utils.get_all_user_subscriptions(user))
        event_types = [sub.event_name for sub in user_subscriptions]

        assert_equal(len(user_subscriptions), 2)  # subscribed to both file_updated and comments
        assert_in('file_updated', event_types)
        assert_in('comments', event_types)

    def test_new_node_creator_is_not_subscribed(self):
        user = factories.UserFactory()
        factories.NodeFactory(creator=user)
        user_subscriptions = list(utils.get_all_user_subscriptions(user))

        assert_equal(len(user_subscriptions), 0)

    def test_new_project_creator_is_subscribed_with_global_settings(self):
        user = factories.UserFactory()

        factories.NotificationSubscriptionFactory(
            _id=user._id + '_' + 'global_comments',