# -*- coding: utf-8 -*-
import string
import pytest

from django.test import TestCase

from .testapp.models import RandomCharTestModel, RandomCharTestModelUnique, RandomCharTestModelLowercase
from .testapp.models import RandomCharTestModelUppercase, RandomCharTestModelAlpha, RandomCharTestModelDigits
from .testapp.models import RandomCharTestModelPunctuation, RandomCharTestModelLowercaseAlphaDigits, RandomCharTestModelUppercaseAlphaDigits
from .testapp.models import RandomCharTestModelUniqueTogether

try:
    from unittest import mock
except ImportError:
    import mock


class RandomCharFieldTest(TestCase):

    def testRandomCharField(self):
        m = RandomCharTestModel()
        m.save()
        assert len(m.random_char_field) == 8, m.random_char_field

    def testRandomCharFieldUnique(self):
        m = RandomCharTestModelUnique()
        m.save()
        assert len(m.random_char_field) == 8, m.random_char_field

    def testRandomCharFieldLowercase(self):
        m = RandomCharTestModelLowercase()
        m.save()
        for c in m.random_char_field:
            assert c.islower(), m.random_char_field

    def testRandomCharFieldUppercase(self):
        m = RandomCharTestModelUppercase()
        m.save()
        for c in m.random_char_field:
            assert c.isupper(), m.random_char_field

    def testRandomCharFieldAlpha(self):
        m = RandomCharTestModelAlpha()
        m.save()
        for c in m.random_char_field:
            assert c.isalpha(), m.random_char_field

    def testRandomCharFieldDigits(self):
        m = RandomCharTestModelDigits()
        m.save()
        for c in m.random_char_field:
            assert c.isdigit(), m.random_char_field

    def testRandomCharFieldPunctuation(self):
        m = RandomCharTestModelPunctuation()
        m.save()
        for c in m.random_char_field:
            assert c in string.punctuation, m.random_char_field

    def testRandomCharTestModelLowercaseAlphaDigits(self):
        m = RandomCharTestModelLowercaseAlphaDigits()
        m.save()
        for c in m.random_char_field:
            assert c.isdigit() or (c.isalpha() and c.islower()), m.random_char_field

    def testRandomCharTestModelUppercaseAlphaDigits(self):
        m = RandomCharTestModelUppercaseAlphaDigits()
        m.save()
        for c in m.random_char_field:
            assert c.isdigit() or (c.isalpha() and c.isupper()), m.random_char_field

    def testRandomCharTestModelDuplicate(self):
        m = RandomCharTestModelUnique()
        m.save()
        with mock.patch('django_extensions.db.fields.RandomCharField.random_char_generator') as func:
            func.return_value = iter([m.random_char_field, 'aaa'])
            m = RandomCharTestModelUnique()
            m.save()
        assert m.random_char_field == 'aaa'

    def testRandomCharTestModelAsserts(self):
        with mock.patch('django_extensions.db.fields.get_random_string') as mock_sample:
            mock_sample.return_value = 'aaa'
            m = RandomCharTestModelUnique()
            m.save()

            m = RandomCharTestModelUnique()
            with pytest.raises(RuntimeError):
                m.save()

    def testRandomCharTestModelUniqueTogether(self):
        with mock.patch('django_extensions.db.fields.get_random_string') as mock_sample:
            mock_sample.return_value = 'aaa'
            m = RandomCharTestModelUniqueTogether()
            m.common_field = 'bbb'
            m.save()

            m = RandomCharTestModelUniqueTogether()
            m.common_field = 'bbb'
            with pytest.raises(RuntimeError):
                m.save()
