from reportlab.lib.styles import  ParagraphStyle,_baseFontNameB,_baseFontNameI,_baseFontNameBI
from reportlab.lib.units import inch
from reportlab.lib import colors
from reportlab.rl_config import canvas_basefontname as _baseFontName
from mdpdfcommon import *
from reportlab.lib.enums import TA_LEFT, TA_CENTER

class MySheet:
    _stylesheet1_undefined = object()

    def __init__(self):
        self.byName = {}
        self.byAlias = {}

    def __getitem__(self, key):
        try:
            return self.byAlias[key]
        except KeyError:
            try:
                return self.byName[key]
            except KeyError:
                raise KeyError("Style '%s' not found in stylesheet" % key)

    def get(self,key,default=_stylesheet1_undefined):
        try:
            return self[key]
        except KeyError:
            if default!=_stylesheet1_undefined: return default
            raise

    def __contains__(self, key):
        return key in self.byAlias or key in self.byName

    def has_key(self,key):
        return key in self

    def add(self, style, alias=None):
        key = style.name
        if key in self.byName:
            raise KeyError("Style '%s' already defined in stylesheet" % key)
        if key in self.byAlias:
            raise KeyError("Style name '%s' is already an alias in stylesheet" % key)

        if alias:
            if alias in self.byName:
                raise KeyError("Style '%s' already defined in stylesheet" % alias)
            if alias in self.byAlias:
                raise KeyError("Alias name '%s' is already an alias in stylesheet" % alias)
        #passed all tests?  OK, add it
        self.byName[key] = style
        if alias:
            self.byAlias[alias] = style

    def list(self):
        styles = list(self.byName.items())
        styles.sort()
        alii = {}
        for (alias, style) in list(self.byAlias.items()):
            alii[style] = alias
        for (name, style) in styles:
            alias = alii.get(style, None)
            print(name, alias)
            style.listAttrs('    ')
            print()


    def getSampleStyleSheet(self):
        """Returns a stylesheet object"""
        stylesheet = MySheet()

        stylesheet.add(ParagraphStyle(name='Normal',
                                      fontName=_baseFontName,
                                      fontSize=10,
                                      leading=12)
                       )
        stylesheet.add(ParagraphStyle(name='Title',
                                      parent=stylesheet['Normal'],
                                      fontName = _baseFontNameB,
                                      fontSize=18,
                                      leading=22,
                                      alignment=TA_CENTER,
                                      spaceAfter=6),
                       alias='title')

        stylesheet.add(ParagraphStyle(name='Title2',
                                  parent=stylesheet['Normal'],
                                  fontName = _baseFontName,
                                  fontSize=13,
                                  leading=22,
                                  alignment=TA_CENTER,
                                  spaceAfter=0),
                        alias='title2')

        stylesheet.add(ParagraphStyle(name='Title3',
                                  parent=stylesheet['Normal'],
                                  fontName = _baseFontName,
                                  fontSize=10,
                                  leading=5,
                                  alignment=TA_CENTER,
                                  spaceAfter=10),
                        alias='title3')

        stylesheet.add(ParagraphStyle(name='Title4',
                          parent=stylesheet['Normal'],
                          fontName = _baseFontName,
                          fontSize=8,
                          leading=10,
                          alignment=TA_CENTER,
                          spaceAfter=5),
                alias='title4')

        stylesheet.add(ParagraphStyle(name='BodyText',
                                      parent=stylesheet['Normal'],
                                      spaceBefore=6)
                       )
        stylesheet.add(ParagraphStyle(name='Italic',
                                      parent=stylesheet['BodyText'],
                                      fontName = _baseFontNameI)
                       )

        stylesheet.add(ParagraphStyle(name='Heading1',
                                      parent=stylesheet['Normal'],
                                      fontName = _baseFontNameB,
                                      fontSize=18,
                                      leading=22,
                                      spaceAfter=6),
                       alias='h1')

        stylesheet.add(ParagraphStyle(name='Heading2',
                                      parent=stylesheet['Normal'],
                                      fontName = _baseFontNameB,
                                      fontSize=14,
                                      leading=18,
                                      spaceBefore=12,
                                      spaceAfter=6),
                       alias='h2')

        stylesheet.add(ParagraphStyle(name='Heading3',
                                      parent=stylesheet['Normal'],
                                      fontName = _baseFontNameBI,
                                      fontSize=12,
                                      leading=14,
                                      spaceBefore=12,
                                      spaceAfter=6),
                       alias='h3')

        stylesheet.add(ParagraphStyle(name='Heading4',
                                      parent=stylesheet['Normal'],
                                      fontName = _baseFontNameBI,
                                      fontSize=10,
                                      leading=12,
                                      spaceBefore=10,
                                      spaceAfter=4),
                       alias='h4')

        stylesheet.add(ParagraphStyle(name='Heading5',
                                      parent=stylesheet['Normal'],
                                      fontName = _baseFontNameB,
                                      fontSize=9,
                                      leading=10.8,
                                      spaceBefore=8,
                                      spaceAfter=4),
                       alias='h5')

        stylesheet.add(ParagraphStyle(name='Heading6',
                                      parent=stylesheet['Normal'],
                                      fontName = _baseFontNameB,
                                      fontSize=7,
                                      leading=8.4,
                                      spaceBefore=6,
                                      spaceAfter=2),
                       alias='h6')

        stylesheet.add(ParagraphStyle(name='Bullet',
                                      parent=stylesheet['Normal'],
                                      firstLineIndent=0,
                                      spaceBefore=3),
                       alias='bu')

        stylesheet.add(ParagraphStyle(name='Definition',
                                      parent=stylesheet['Normal'],
                                      firstLineIndent=0,
                                      leftIndent=36,
                                      bulletIndent=0,
                                      spaceBefore=6,
                                      bulletFontName=_baseFontNameBI),
                       alias='df')

        stylesheet.add(ParagraphStyle(name='Code',
                                      parent=stylesheet['Normal'],
                                      fontName='Courier',
                                      fontSize=8,
                                      leading=8.8,
                                      firstLineIndent=0,
                                      leftIndent=36))

        return stylesheet


class DefaultTheme(object):
    s=MySheet()
    _s = s.getSampleStyleSheet()

    doc = {
        'leftMargin': None,
        'rightMargin': None,
        'topMargin': None,
        'bottomMargin': None
        }
    headers = {
         H1: _s['Heading1'],
         H2: _s['Heading2'],
         H3: _s['Heading3'],
         H4: _s['Heading4'],
         H5: _s['Heading5'],
         H6: _s['Heading6'],
         T1: _s['Title'],
         T2: _s['Title2'],
         T3: _s['Title3'],
         T4: _s['Title4']
         }

    paragraph = _s['Normal']

    spacer_height = 0.25 * inch
    table_style = [
        ('ALIGN', (0,0), (-1,-1), 'LEFT'),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
        ('FONT', (0,0), (-1,0), 'Helvetica-Bold'),
        ('LINEBELOW', (0,0), (-1,0), 1, colors.black),
        ('BACKGROUND', (0,0), (-1,0), colors.HexColor('#C0C0C0')),
        ('ROWBACKGROUNDS', (0,1), (-1, -1), [colors.white, colors.HexColor('#E0E0E0')])
        ]




    @classmethod
    def doc_template_args(cls):
        return dict([(k, v) for k, v in cls.doc.items() if v is not None])
    
    @classmethod    
    def header_for_level(cls, level):
        return cls.headers[level]

    def __new__(cls, *args, **kwargs):
        raise TypeError("Theme classes may not be instantiated.")

def calc_table_col_widths(rows, table_width):
    max_chars_per_col = [0] * len(rows[0])
    for row in rows:
        for idx, col in enumerate(row):
            for line in str(col).split('\n'):
                max_chars_per_col[idx] = max(len(line),
                    max_chars_per_col[idx])
    sum_chars = sum(max_chars_per_col)
    return [(x * table_width / sum_chars) for x in max_chars_per_col]

_stylesheet1_undefined = object()
