# -*- coding: utf-8 -*-
import itertools
from django.conf import settings
from django.template import Template, Context
import django_tables2 as tables
from django_attest import TestContext
from attest import Tests, Assert
from .app.models import Person, Occupation


models = Tests()
models.context(TestContext())


class PersonTable(tables.Table):
    first_name = tables.Column()
    last_name = tables.Column()
    occupation = tables.Column()


@models.test
def boundrows_iteration():
    occupation = Occupation.objects.create(name='Programmer')
    Person.objects.create(first_name='Bradley', last_name='Ayers', occupation=occupation)
    Person.objects.create(first_name='Chris',   last_name='Doble', occupation=occupation)

    table = PersonTable(Person.objects.all())
    records = [row.record for row in table.rows]
    expecteds = Person.objects.all()
    for expected, actual in itertools.izip(expecteds, records):
        Assert(expected) == actual


@models.test
def model_table():
    """
    The ``model`` option on a table causes the table to dynamically add columns
    based on the fields.
    """
    class OccupationTable(tables.Table):
        class Meta:
            model = Occupation
    Assert(["id", "name", "region"]) == OccupationTable.base_columns.keys()

    class OccupationTable2(tables.Table):
        extra = tables.Column()
        class Meta:
            model = Occupation
    Assert(["id", "name", "region", "extra"]) == OccupationTable2.base_columns.keys()

    # be aware here, we already have *models* variable, but we're importing
    # over the top
    from django.db import models
    class ComplexModel(models.Model):
        char = models.CharField(max_length=200)
        fk = models.ForeignKey("self")
        m2m = models.ManyToManyField("self")

    class ComplexTable(tables.Table):
        class Meta:
            model = ComplexModel
    Assert(["id", "char", "fk"]) == ComplexTable.base_columns.keys()


@models.test
def mixins():
    class TableMixin(tables.Table):
        extra = tables.Column()

    class OccupationTable(TableMixin, tables.Table):
        extra2 = tables.Column()
        class Meta:
            model = Occupation
    Assert(["extra", "id", "name", "region", "extra2"]) == OccupationTable.base_columns.keys()


@models.test
def verbose_name():
    """
    When using queryset data as input for a table, default to using model field
    verbose names rather than an autogenerated string based on the column name.

    However if a column does explicitly describe a verbose name, it should be
    used.
    """
    class PersonTable(tables.Table):
        """
        The test_colX columns are to test that the accessor is used to
        determine the field on the model, rather than the column name.
        """
        first_name = tables.Column()
        fn1 = tables.Column(accessor='first_name')
        fn2 = tables.Column(accessor='first_name.upper')
        fn3 = tables.Column(accessor='last_name', verbose_name='OVERRIDE')
        last_name = tables.Column()
        ln1 = tables.Column(accessor='last_name')
        ln2 = tables.Column(accessor='last_name.upper')
        ln3 = tables.Column(accessor='last_name', verbose_name='OVERRIDE')
        region = tables.Column(accessor='occupation.region.name')
        r1 = tables.Column(accessor='occupation.region.name')
        r2 = tables.Column(accessor='occupation.region.name.upper')
        r3 = tables.Column(accessor='occupation.region.name', verbose_name='OVERRIDE')
        trans_test = tables.Column()
        trans_test_lazy = tables.Column()

    # The Person model has a ``first_name`` and ``last_name`` field, but only
    # the ``last_name`` field has an explicit ``verbose_name`` set. This means
    # that we should expect that the two columns that use the ``last_name``
    # field should both use the model's ``last_name`` field's ``verbose_name``,
    # however both fields that use the ``first_name`` field should just use a
    # capitalized version of the column name as the column header.
    table = PersonTable(Person.objects.all())
    # Should be generated (capitalized column name)
    Assert('first name') == table.columns['first_name'].verbose_name
    Assert('first name') == table.columns['fn1'].verbose_name
    Assert('first name') == table.columns['fn2'].verbose_name
    Assert('OVERRIDE') == table.columns['fn3'].verbose_name
    # Should use the model field's verbose_name
    Assert('surname') == table.columns['last_name'].verbose_name
    Assert('surname') == table.columns['ln1'].verbose_name
    Assert('surname') == table.columns['ln2'].verbose_name
    Assert('OVERRIDE') == table.columns['ln3'].verbose_name
    Assert('name') == table.columns['region'].verbose_name
    Assert('name') == table.columns['r1'].verbose_name
    Assert('name') == table.columns['r2'].verbose_name
    Assert('OVERRIDE') == table.columns['r3'].verbose_name
    Assert("translation test") == table.columns["trans_test"].verbose_name
    Assert("translation test lazy") == table.columns["trans_test_lazy"].verbose_name

    # -------------------------------------------------------------------------

    # Now we'll try using a table with Meta.model
    class PersonTable(tables.Table):
        class Meta:
            model = Person
    # Issue #16
    table = PersonTable([])
    Assert("translation test") == table.columns["trans_test"].verbose_name
    Assert("translation test lazy") == table.columns["trans_test_lazy"].verbose_name


@models.test
def field_choices_used_to_translated_value():
    """
    When a model field uses the ``choices`` option, a table should render the
    "pretty" value rather than the database value.

    See issue #30 for details.
    """
    LANGUAGES = (
        ('en', 'English'),
        ('ru', 'Russian'),
    )

    from django.db import models

    class Article(models.Model):
        name = models.CharField(max_length=200)
        language = models.CharField(max_length=200, choices=LANGUAGES)

        def __unicode__(self):
            return self.name

    class ArticleTable(tables.Table):
        class Meta:
            model = Article

    table = ArticleTable([Article(name='English article', language='en'),
                          Article(name='Russian article', language='ru')])

    Assert('English') == table.rows[0]['language']
    Assert('Russian') == table.rows[1]['language']


@models.test
def column_mapped_to_nonexistant_field():
    """
    Issue #9 describes how if a Table has a column that has an accessor that
    targets a non-existent field, a FieldDoesNotExist error is raised.
    """
    class FaultyPersonTable(PersonTable):
        missing = tables.Column()

    table = FaultyPersonTable(Person.objects.all())
    table.as_html()  # the bug would cause this to raise FieldDoesNotExist


@models.test
def should_support_rendering_multiple_times():
    class MultiRenderTable(tables.Table):
        name = tables.Column()

    # test queryset data
    table = MultiRenderTable(Person.objects.all())
    assert table.as_html() == table.as_html()
