import logging
import time

from pyquery import PyQuery as pq

from django.conf import settings
from django.db import connection

from django.contrib.auth.models import AnonymousUser, User

from django.test import TestCase
from django.test.client import Client

from nose.tools import assert_equal, with_setup, assert_false, eq_, ok_
from nose.plugins.attrib import attr

from django.db import models

from django.core.urlresolvers import reverse

from ..models import Key
from ..views import ITEMS_PER_PAGE


class KeyViewsTest(TestCase):

    def setUp(self):
        self.username = 'tester23'
        self.password = 'trustno1'
        self.email = 'tester23@example.com'

        self.user = User(username=self.username,
                         email=self.email)
        self.user.set_password(self.password)
        self.user.save()

        self.user2 = User(username='someone', email='someone@example.com')
        self.user2.save()

        self.key1 = Key(user=self.user, description='Test Key 1')
        self.key1.save()
        self.key2 = Key(user=self.user, description='Test Key 2')
        self.key2.save()
        self.key3 = Key(user=self.user2, description='Test Key 3')
        self.key3.save()

        self.client = Client()

    def tearDown(self):
        self.user.delete()
        self.user2.delete()
        self.key1.delete()
        self.key2.delete()
        self.key3.delete()

    def test_new_key(self):
        self.client.login(username=self.username,
                          password=self.password)
        data = {"description": "This is meant for a test app"}
        url = reverse('valet_keys.new')

        # Check out the creation page, look for the form.
        resp = self.client.get(url)
        eq_(200, resp.status_code)
        page = pq(resp.content)
        eq_(1, page.find('form.key').length)

        # We don't have this key yet, right?
        keys = Key.objects.filter(description=data['description'])
        eq_(0, keys.count())

        # Okay, create it.
        resp = self.client.post(url, data, follow=False)
        eq_(200, resp.status_code)

        # We have the key now, right?
        keys = Key.objects.filter(description=data['description'])
        eq_(1, keys.count())

        # Okay, and it should belong to the logged-in user
        key = keys[0]
        eq_(key.user, self.user)

        # Take a look at the description and key shown on the result page.
        page = pq(resp.content)
        ok_(data['description'], page.find('.key .description').text())
        ok_(key.key, page.find('.key .key').text())

        # Ensure the secret on the page checks out.
        secret = page.find('.key .secret').text()
        ok_(key.check_secret(secret))

    def test_list_key(self):
        """The current user's keys should be shown, but only that user's"""
        self.client.login(username=self.username,
                          password=self.password)

        url = reverse('valet_keys.list')
        resp = self.client.get(url)
        eq_(200, resp.status_code)
        page = pq(resp.content)

        for ct, key in ((1, self.key1), (1, self.key2), (0, self.key3)):
            key_row = page.find('.keys #key-%s' % key.pk)
            eq_(ct, key_row.length)
            if ct > 0:
                eq_(key.description, key_row.find('.description').text())

    def test_key_history(self):
        self.client.login(username=self.username,
                          password=self.password)

        # Assemble some sample log lines
        log_lines = []
        for i in range(0, ITEMS_PER_PAGE * 2):
            log_lines.append(('ping', self.user2, 'Number #%s' % i))

        # Record the log lines for this key
        for l in log_lines:
            self.key1.log(*l)

        # Reverse the lines for comparison.
        log_lines.reverse()

        # Iterate through 2 expected pages...
        for qs, offset in (('', 0), ('?page=2', ITEMS_PER_PAGE)):
            url = '%s%s' % (reverse('valet_keys.history', args=(self.key1.pk,)), qs)
            resp = self.client.get(url)
            eq_(200, resp.status_code)
            page = pq(resp.content)

            rows = page.find('.item')
            for idx in range(0, ITEMS_PER_PAGE):
                row = rows.eq(idx)
                expected = log_lines[idx + offset]
                line = (row.find('.action').text(),
                        row.find('.object').text(),
                        row.find('.notes').text())
                eq_(expected[0], line[0])
                ok_('%s' % expected[1] in line[1])
                eq_(expected[2], line[2])

    def test_disable_key(self):
        """User should be able to disable own keys, but no one else's"""
        self.client.login(username=self.username,
                          password=self.password)

        url = reverse('valet_keys.disable', args=(self.key3.pk,))
        resp = self.client.get(url, follow=True)
        eq_(403, resp.status_code)

        resp = self.client.post(url, follow=False)
        ok_(403, resp.status_code)

        url = reverse('valet_keys.list')
        resp = self.client.get(url)
        eq_(200, resp.status_code)
        page = pq(resp.content)
        eq_(0, page.find('#key-%s.disabled' % self.key1.pk).length)

        ok_(not Key.objects.get(pk=self.key1.pk).is_disabled)

        url = reverse('valet_keys.disable', args=(self.key1.pk,))
        resp = self.client.get(url, follow=True)
        eq_(200, resp.status_code)

        page = pq(resp.content)
        eq_(self.key1.description, page.find('.key .description').text())

        resp = self.client.post(url, follow=False)
        ok_(302, resp.status_code)

        url = reverse('valet_keys.list')
        resp = self.client.get(url)
        eq_(200, resp.status_code)
        page = pq(resp.content)
        eq_(1, page.find('#key-%s.disabled' % self.key1.pk).length)

        ok_(Key.objects.get(pk=self.key1.pk).is_disabled)
