"""
Binder views tests.
"""
import os
import unittest

from django.conf import settings
from django.test.client import Client
from django.core.urlresolvers import reverse, resolve
from django.core import mail

from rldjango.apps.binder.models import Section
from utils import check_test_mode


class ViewsTestCase(unittest.TestCase):
    """
    Base view test case with shortcuts..
    """
    def setUp(self): # pylint: disable-msg=C0103
        """
        Prepare variables.
        """
        check_test_mode()
        self.client = Client()

    def get(self, view_name, *args, **kwargs):
        """
        Get request shortcut.
        """
        get_params = kwargs.pop("client_get", {})
        return self.client.get(reverse(view_name, args=args, kwargs=kwargs), get_params)

    def post(self, view_name, *args, **kwargs):
        """
        Post request shortcut.
        """
        data = kwargs.pop("data", None)
        return self.client.post(reverse(view_name, args=args, kwargs=kwargs), data)

class ViewTests(ViewsTestCase):
    """
    Test choose, create, create with preselected sections and download
    """

    def test_list(self):
        """
        Test brochure list view.
        """
        # Brochure listing now hidden to non-logged-in visitors
        response = self.get('binder_choose')
        self.assertEqual(response.status_code, 302)
        
        self.client.login(username='bindertestuser', password='password')
        response = self.get('binder_choose')
        self.assertTrue('binder_test_pdf' in response.content, 'Response\n%r\nDoes not contain binder_test_pdf' % response.content)

    def test_create(self):
        """
        Test brochure list view.
        """
        response = self.get('binder_create', 'binder_test_pdf')

        self.assertTrue('<input checked="checked" type="checkbox" name="section_6" id="id_section_6" />' in response.content)
        self.assertTrue('<input type="checkbox" name="section_4" id="id_section_4" />' in response.content)
        self.assertTrue('<h1 id="caption">This is the test brochure</h1>' in response.content)
        self.assertTrue('<div id="footer">For testing purposes only</div>' in response.content)

    def test_create_preselected(self):
        """
        Test brochure list view.
        """
        response = self.get(
            'binder_create',
            'binder_test_pdf',
            client_get={'sections': '4,6'})
        
        preselected_text = ('<input checked="checked" type="checkbox"'
                            ' name="section_4" id="id_section_4" />')
        self.assertTrue(preselected_text in response.content)
        
        # Test by slug id
        response = self.get(
            'binder_create',
            'binder_test_pdf',
            client_get={'sections': 'section-2'})
        
        preselected_text = ('<input checked="checked" type="checkbox"'
                            ' name="section_5" id="id_section_5" />')
        self.assertTrue(preselected_text in response.content)
        
        # Test by abstract section
        response = self.get(
            'binder_create',
            'binder_test_pdf',
            client_get={'sections': 'abstract-section-1'})
        
        preselected_text = ('<input checked="checked" type="checkbox"'
                            ' name="section_3" id="id_section_3" />')
        self.assertTrue(preselected_text in response.content)
        
        # Test sections-expanded
        response = self.get(
            'binder_create',
            'binder_test_pdf',
            client_get={'sections-expanded': '5'})
        
        #preselected_text = ('<span class="title toggle expanded">'
        #    '<span class="bullet">'
        #      '+'
        #    '</span>'
        #    'Abstract Section 2'
        #  '</span>')
        #self.assertTrue(preselected_text in response.content)

    def test_create_pdf(self):
        """
        Test pdf creating. We need DEBUG = True to produce last rml.
        """
        debug = settings.DEBUG
        settings.DEBUG = True

        response = self.post(
            'binder_create',
            'binder_test_pdf',
            data={
                u'section_3': [u'on'],
                u'section_4': [u'on'],
                u'blurb': [u'blurb is present']}
            )

        # pylint: disable-msg=W0212
        url = resolve(response._headers['location'][1].replace('http://testserver', ''))
        pdf_info = url[2]['pdf_md5']

        self.assertTrue(
            os.path.isfile(
                os.path.join(settings.OUTPUT_ROOT, '%s.pdf' % pdf_info)))

        _file = open(settings.LAST_RML, 'r')
        rml = _file.read()
        _file.close()
        self.assertTrue('<doForm name="section_form_4"' in rml)
        self.assertTrue('<setNextTemplate name="toc"' in rml)
        self.assertTrue('This customised brochure was created on demand in seconds' in rml)
        self.assertTrue('<bookmark name="bookmark_section_4"' in rml)
        self.assertTrue('<pageTemplate id="page_rotated_left"' in rml)
        self.assertTrue('<setNextTemplate name="page_rotated_left"/>' in rml)
        self.assertTrue('blurb is present' in rml)
        
        settings.DEBUG = debug

    def test_search_params(self):
        """
        test that parameters from search page result in the appropriate options 
        on the download page
        """
        # we need to append the url parameters to the call to 'reverse',
        # since this is a post
        response=self.client.post(reverse('binder_create',
                                    args=['binder_test_pdf',])+"/?download_display=12&download_option=2", 
                                    {u'section_3': [u'on'],
                                    u'section_4': [u'on']},
                                    follow=True)

        # check that the correct options are displayed on the resulting page 
        # download and flipbook present, no email option
        self.assertFalse('<input type="radio" name="action" value="email" ' in response.content)
        self.assertTrue('<input style="visibility:visible" type="radio" id="id_action_0" value="download" name="action" /> Download PDF' in response.content)
        # check that flipbook option is present and selected
        self.assertTrue('<input style="visibility:visible" checked="checked" name="action" value="flip_book" type="radio" id="id_action_1" /> View PDF as flip book' in response.content)

        
    def test_flipbook(self):
        """
        Test we get the correct JS containing flipbook images and that images are available
        """
        response = self.post(
            'binder_create',
            'binder_test_pdf',
            data={
                u'section_3': [u'on'],
                u'section_4': [u'on']}
            )

        url = resolve(response._headers['location'][1].replace('http://testserver', ''))
        pdf_info = url[2]['pdf_md5']

        # check flipbook page exists for generated brochure
        response_page = self.get('binder_flipbook', 'binder_test_pdf', pdf_info)
        self.assertEqual(response_page.status_code, 200)
        
        # are flippingbook and generated JS files there?
        self.assertTrue('<script type="text/javascript" src="/media/binder/flip_book/js/flippingbook.js"></script>' in response_page.content)
        response = self.client.get('/media/binder/flip_book/js/flippingbook.js')
        self.assertTrue('<script type="text/javascript" src="/media/output/%s.js"></script>' % pdf_info in response_page.content)
        response = self.client.get('/media/output/%s.js' % pdf_info)
        
        # is the list of flip book images there and can we download one of the 
        self.assertTrue('flippingBook.pages' in response.content)
        self.assertTrue('/media/sections/binder_test_pdf_page_0001.jpg' in response.content)
        response = self.client.get('/media/sections/binder_test_pdf_page_0001.jpg')
        self.assertEqual(response.status_code, 200)

    def test_email(self):
        """
        test sending a brochure as an email attachment.
        Only works with a logged in user, because of the captcha.
        """
        self.client.login(username='bindertestsuperuser', password='password')
        
        response = self.post(
            'binder_create',
            'binder_test_pdf',
            data={
                u'section_3': [u'on'],
                u'section_4': [u'on']}
            )

        url = resolve(response._headers['location'][1].replace('http://testserver', ''))
        pdf_info = url[2]['pdf_md5']
        response_page = self.get('binder_download', 'binder_test_pdf', pdf_info)

        #test that emailing without 'email_to' fails
        response2=self.client.post(reverse('binder_download', 
                                   args=['binder_test_pdf', pdf_info]), 
                                   {'action':['email']},
                                   follow=True)
        self.assertTrue('This field is required.' in response2.content)

        #test with 'email_to' set
        response2=self.client.post(reverse('binder_download', 
                                   args=['binder_test_pdf', pdf_info]), 
                                   {'action':['email'],'email_to':['test@reportlab.com']},
                                   follow=True)
        self.assertEquals(len(mail.outbox), 1)
        self.assertEquals(mail.outbox[0].subject, 'You have been sent an eBrochure.')
        self.assertEquals(len(mail.outbox[0].attachments), 1)
        
    def test_api(self):
        response = self.get('help', 'binder_test_pdf')
        self.assertEqual(response.status_code, 200)
        response = self.get('api', 'binder_test_pdf')
        self.assertEqual(response.status_code, 200) # PA 500 was expected
        
        # disposition=html should return a page which has the sections and other variables hidden in it
        response = self.get('api', 'binder_test_pdf',
            client_get={
                'sections': '4,6',
                'disposition': 'html'})
        self.assertEqual(response.status_code, 200) # PA content now consists of a html page with a link to the PDF
        
        #self.assertTrue('section_4' in response.content) 
        #self.assertTrue('section_6' in response.content)
        
        # disposition=inline should return content type inline
        response = self.get('api', 'binder_test_pdf',
            client_get={
                'sections': '4,6',
                'disposition': 'inline'})
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response['Content-disposition'], 'inline; filename=brochure.pdf')
        self.assertEqual(response['Content-Type'], 'application/pdf')
        
        # disposition=attachment should return download PDF
        response = self.get('api', 'binder_test_pdf',
            client_get={
                'sections': '4,6',
                'disposition': 'attachment'})
        
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response['Content-disposition'], 'attachment; filename=brochure.pdf')
        self.assertEqual(response['Content-Type'], 'application/pdf')
        
        # disposition=url should return text/plain with the URL in it
        response = self.get('api', 'binder_test_pdf',
            client_get={
                'sections': '4,6',
                'disposition': 'url'})
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response['Content-Type'], 'text/plain; charset=utf-8')
        self.assertTrue('http://' in response.content)
        self.assertTrue('.pdf' in response.content)
        
        # disposition=flipbook should return 302 redirect
        response = self.get('api', 'binder_test_pdf',
            client_get={
                'sections': '4,6',
                'disposition': 'flip_book'})
        self.assertEqual(response.status_code, 302)
        response = self.client.get(reverse('api', args=['binder_test_pdf',]), {
                'sections': '4,6',
                'disposition': 'flip_book'},
                follow=True)
        self.assertEqual(response.status_code, 200)
        next_url = response.redirect_chain[-1][0]
        response = self.client.get(next_url)
        self.assertTrue('<script type="text/javascript" src="/media/binder/flip_book/js/flippingbook.js"></script>' in response.content)
        

        
        # Email disposition should cause error if correct sending parameters aren't sent
        response = self.get('api', 'binder_test_pdf',
            client_get={
                'sections': '4,6',
                'disposition': 'email'})
        self.assertEqual(response.status_code, 500)
        self.assertTrue("You need to supply an 'email_to' parameter" in response.content)
        
        # If email is sent, should return 200 and a confirmation message
        response = self.get('api', 'binder_test_pdf',
            client_get={
                'sections': '4,6',
                'disposition': 'email',
                'email_to': 'test@reportlab.com'})
        self.assertEqual(response.status_code, 200)
        self.assertTrue('Your eBrochure email has been sent.' in response.content)
    
    
    def test_create_customised(self):
        """
        test for presence/absence of extra fields on 'create' web page, depending on login status
        """
        #no login - field should not appear
        response = self.get('binder_create', 'binder_test_pdf')
        self.assertFalse('<input type="text" name="blurb" id="blurb" size="40">' in response.content)
        
        #login as owner- field should appear
        self.client.login(username='bindertestuser', password='password')
        response = self.get('binder_create', 'binder_test_pdf')
        self.assertTrue('<input type="text" name="blurb" id="blurb" size="40">' in response.content)
        
        #login as someone else (who isn't a superuser) - field should not appear
        self.client.login(username='bindertestnotowner', password='password')
        response = self.get('binder_create', 'binder_test_pdf')
        self.assertFalse('<input type="text" name="blurb" id="blurb" size="40">' in response.content)
        
        #login as someone else (who is a superuser) - field should appear
        self.client.login(username='bindertestsuperuser', password='password')
        response = self.get('binder_create', 'binder_test_pdf')
        self.assertTrue('<input type="text" name="blurb" id="blurb" size="40">' in response.content)
        
