# -*- coding: utf-8 -*-
from mock import patch
from unittest import TestCase
from distribution import app
from flask_api_auth.models import APIUser, APIRole


class ResourceTestCase(TestCase):

    def setUp(self):
        self.maxDiff = None
        self.context = app
        self.context.config['DEBUG'] = True
        self.context.config['TESTING'] = True
        self.app = app.test_client()


def get_user_mock(name='Luke', key='1234'):
    return APIUser({'name': name, 'key': key, 'is_active': True, 'roles': ['admin']},
                   validate=False)


def get_role_mock(name='admin', permissions={}):
    return APIRole(
        {
            'name': name,
            'permissions': permissions,
            'is_active': True,
            'valid_until': None
        },
        validate=False)


class AuthResourceTestCaseMixin(object):
    apiuser = 'yoda'
    apikey = '456123'

    def setUp(self):
        super(AuthResourceTestCaseMixin, self).setUp()
        manager_save_patcher = patch('distribution.managers.BaseManager.save')
        self.addCleanup(manager_save_patcher.stop)
        self.manager_save_mock = manager_save_patcher.start()

    def get_auth_headers(self, **kwargs):
        headers = kwargs.setdefault('headers', {})
        headers.update({'ApiAuth-ApiUser': self.apiuser,
                        'ApiAuth-ApiKey': self.apikey})

        return kwargs

    def get_with_auth(self, url, *args, **kwargs):
        kwargs = self.get_auth_headers(**kwargs)

        return self.app.get(url, *args, **kwargs)

    def post_with_auth(self, url, *args, **kwargs):
        kwargs = self.get_auth_headers(**kwargs)
        return self.app.post(url, *args, **kwargs)

    def put_with_auth(self, url, *args, **kwargs):
        kwargs = self.get_auth_headers(**kwargs)
        return self.app.put(url, *args, **kwargs)

    def delete_with_auth(self, url, *args, **kwargs):
        kwargs = self.get_auth_headers(**kwargs)
        return self.app.delete(url, *args, **kwargs)

    def fake_authentication(self, allowed=True):
        """
        This patches the flask_api_auth decorator to make it always
        succeed or fail password validation, as given by the "allowed"
        parameter.

        Use it in the same way as mock.patch().

        """
        user_mock = get_user_mock(name=self.apiuser, key=self.apikey)
        role_mock = get_role_mock()

        return [patch('distribution.managers.auth.APIUserManager.get',
                      return_value=user_mock),
                patch('flask_api_auth.models.APIUser.verify_password',
                      return_value=allowed),
                patch('distribution.managers.auth.RoleManager.get',
                      return_value=role_mock)]
