# -*- coding: utf-8 -*-

# Copyright (C) 2016 Avencall
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

from hamcrest import (assert_that,
                      empty,
                      has_entries,
                      has_length,
                      not_)
from test_api import associations as a
from test_api import confd
from test_api import errors as e
from test_api import fixtures
from test_api import scenarios as s
from test_api.bus import BusClient
from xivo_test_helpers import until
import unittest


FAKE_ID = 999999999

class TestUserEntity(unittest.TestCase):

    @fixtures.entity()
    @fixtures.user()
    def test_associate_errors(self, entity, user):
        fake_user = confd.users(FAKE_ID).entities(entity['id']).put
        fake_entity = confd.users(user['id']).entities(FAKE_ID).put

        yield s.check_resource_not_found, fake_user, 'User'
        yield s.check_resource_not_found, fake_entity, 'Entity'


    def test_get_errors(self):
        fake_user = confd.users(FAKE_ID).entities.get
        yield s.check_resource_not_found, fake_user, 'User'


    @fixtures.entity()
    @fixtures.user()
    def test_associate_user_entity(self, entity, user):
        response = confd.users(user['id']).entities(entity['id']).put()
        response.assert_updated()


    @fixtures.entity()
    @fixtures.user()
    def test_associate_using_uuid(self, entity, user):
        response = confd.users(user['uuid']).entities(entity['id']).put()
        response.assert_updated()


    @fixtures.entity()
    @fixtures.user()
    def test_get_entities_associated_to_user(self, entity, user):
        expected = has_entries({'user_id': user['id'],
                                'entity_id': entity['id']})

        with a.user_entity(user, entity):
            response = confd.users(user['id']).entities.get()
            assert_that(response.item, expected)

            response = confd.users(user['uuid']).entities.get()
            assert_that(response.item, expected)


    @fixtures.entity()
    @fixtures.entity()
    @fixtures.user()
    def test_associate_when_user_already_associated_to_other_entity(self, entity1, entity2, user):
        with a.user_entity(user, entity1):
            response = confd.users(user['id']).entities(entity2['id']).put()
            response.assert_updated()


    @fixtures.entity()
    @fixtures.user()
    def test_associate_when_user_already_associated_to_same_entity(self, entity, user):
        with a.user_entity(user, entity):
            response = confd.users(user['id']).entities(entity['id']).put()
            response.assert_match(400, e.resource_associated('User', 'Entity'))


    @fixtures.entity()
    @fixtures.user()
    @fixtures.line_sip()
    def test_associate_when_user_already_associated_to_a_line(self, entity, user, line):
        with a.user_line(user, line):
            response = confd.users(user['id']).entities(entity['id']).put()
            response.assert_match(400, e.resource_associated('User', 'Line'))


    @fixtures.entity()
    @fixtures.user()
    def test_delete_user_when_user_and_entity_associated(self, entity, user):
        with a.user_entity(user, entity, check=False):
            response = confd.users(user['id']).entities.get()
            assert_that(response.item, not_(empty()))
            confd.users(user['id']).delete().assert_deleted()
            invalid_user = confd.users(user['id']).entities.get
            s.check_resource_not_found(invalid_user, 'User')


    @fixtures.entity()
    @fixtures.user()
    def test_bus_event_when_associate(self, entity, user):
        BusClient.listen_delayed_events('config.users.{}.entities.updated'.format(user['uuid']))
        with a.user_entity(user, entity):
            def assert_function():
                assert_that(BusClient.drain_events(), has_length(1))

            until.assert_(assert_function, tries=5)
