"""Various reusable utils/helpers"""
import os, copy

from django.test import Client
from django.core.handlers.wsgi import WSGIRequest
from reportlab.pdfbase.pdfmetrics import stringWidth, registerFont


breadcrumb = []

class RequestFactory(Client):
    """
    Class that lets you create mock Request objects for use in testing.
    
    Usage:
    
    rf = RequestFactory()
    get_request = rf.get('/hello/')
    post_request = rf.post('/submit/', {'foo': 'bar'})
    
    This class re-uses the django.test.client.Client interface, docs here:
    http://www.djangoproject.com/documentation/testing/#the-test-client
    
    Once you have a request object you can pass it to any view function, 
    just as if that view had been hooked up using a URLconf.
    
    """
    def request(self, **request):
        """
        Similar to parent class, but returns the request object as soon as it
        has created it.
        """
        environ = {
            'HTTP_COOKIE': self.cookies,
            'PATH_INFO': '/',
            'QUERY_STRING': '',
            'REQUEST_METHOD': 'GET',
            'SCRIPT_NAME': '',
            'SERVER_NAME': 'testserver',
            'SERVER_PORT': 80,
            'SERVER_PROTOCOL': 'HTTP/1.1',
            'REMOTE_ADDR': '192.168.0.1'
        }
        environ.update(self.defaults)
        environ.update(request)
        return WSGIRequest(environ)

def prepare_toc_entry(text=None, toc_id=None, context=None, level=0, text_width=300, font='toc_font'):
    """
    Do some logic with toc entry. Calculates rect x and width
    """
    
    font = context[font]
    if text is None:  #some nulls in their data
        text = ''
    new_text = level * '    ' + text

    if toc_id:
        new_text_width = stringWidth(new_text, font['name'], font['size'])
        if new_text_width > text_width:
            new_text = new_text.split('.')[0]
            new_text_width = stringWidth(new_text, font['name'], font['size'])
        return {
            'name': new_text,
            'id': "toc_%s" % toc_id,
            'rect': {
                'x': new_text_width + 10,
                'width': text_width - new_text_width - 10
                }
            }
    else:
        return {
            'name': new_text,
            }
        

def prepare_outline_entry(text=None, level=0):
    """
    Prepare standard outline entry.
    """
    global breadcrumb
    breadcrumb = breadcrumb[0:level]
    breadcrumb.append(text)
        
    return {
        'name': text,
        'level': level,
        'breadcrumb': copy.deepcopy(breadcrumb)
        }

def create_pairs(obj):
    """
    Create list of pairs from list.
    """
    return zip(obj[::2], obj[1::2])

def create_guide(context, brochure, toc, node, outline_level=0, toc_level=0,
                 template='narrative', exclude=[]):
    """
    Recursive function to add guide to brochure.
    """
    
    if node.name not in exclude:
        entry = {
            # 'new_page': {
            #     'before': True,
            #     'template': 'accommodation',
            #     'after': True,
            #     },
            # 'toc_entry': toc_entry,
            'keep_in_frame': False,
            'obj': node
            }

        new_page_before = False
        if toc_level == 0:
            new_page_before = True

        if toc_level < 2:
            toc_entry = prepare_toc_entry(text=node.name, toc_id=node.get_uniq_id(),
                                          context=context, level=toc_level)
            toc.append(toc_entry)

            entry['new_page'] = {
                'before': new_page_before,
                'template': template,
                'after': False,
                }
            entry['toc_entry'] = toc_entry
        entry['outline_entry'] = prepare_outline_entry(text=node.name, level=outline_level)
        # TODO: smaller headings for subheadings
        brochure.append(entry)

        outline_level += 1
        toc_level += 1
        for child in node.children.all():
            create_guide(context, brochure, toc, child, outline_level, toc_level,
                         template=template, exclude=exclude)

    
