#!/usr/bin/env python

"calbum.py - A program for making simple PDF calendar albums."

__author__ = 'Dinu Gherman <dinu@mac.com>'
__version__ = '0.3.0'

import sys, glob, getopt, locale, datetime, calendar
from os.path import join, dirname

from reportlab import rl_config
from reportlab.lib import colors
from reportlab.lib.units import cm
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT

from reportlab.platypus.paragraph import Paragraph
from reportlab.platypus.flowables import Spacer, Image, PageBreak
from reportlab.platypus.frames import Frame
from reportlab.platypus.tables import TableStyle, Table
from reportlab.platypus.doctemplate \
    import PageTemplate, BaseDocTemplate


WIDTH = (21-4)*cm
styleSheet = getSampleStyleSheet()
h1 = styleSheet['Heading1']
h1.alignment = TA_CENTER
h1.fontSize = 24
h2 = styleSheet['Heading2']
bt = styleSheet['BodyText']
bt.leading = bt.fontSize*1


class MyTemplate(BaseDocTemplate):
    "The document template used for all PDF documents."

    def __init__(self, filename, **kw):
        m = (21*cm - WIDTH)/2.0
        frame1 = Frame(m, m, WIDTH, (29.5-3)*cm, id='F1')
        apply(BaseDocTemplate.__init__, (self, filename), kw)
        self.addPageTemplates(PageTemplate('normal', [frame1]))


def getLtext(lcode):
    "Get localised text for some locale code."

    ltext = locale.nl_langinfo(lcode).capitalize()
    if sys.platform == "darwin":
        if rl_config.defaultEncoding == "MacRomanEncoding":
            return ltext.decode("latin1").encode("macroman")
    return ltext


def rotate(seq, steps=1):
    "Rotate a sequence by some steps, left/right if pos./neg."

    return seq[steps:] + seq[:steps]


def makeTable(year, month, day2text={}):
    "Create a Platypus table for a given month."

    # just to be sure...
    firstday = calendar.MONDAY
    restdays = [calendar.SATURDAY, calendar.SUNDAY]
    restdays = [(d - firstday) % 7 for d in restdays]
    calendar.setfirstweekday(firstday)

    # make table header line
    redFormat = '<font color="red">%s</font>'
    nums = range(locale.ABDAY_1, locale.ABDAY_7 + 1)
    weekdays = [getLtext(n) for n in rotate(nums)]
    weekdays = rotate(weekdays, firstday)
    weekdays = ["<b>%s</b>" % d for d in weekdays]
    for d in restdays: weekdays[d] = redFormat % weekdays[d]
    weekdays = [Paragraph(d, h1) for d in weekdays]

    # make numbers, remove zeros
    weeks = calendar.monthcalendar(year, month)
    for i in range(len(weeks)):
        weeks[i] = [str(d or '') for d in weeks[i]]

    # add text for special days
    day2xy = {}
    for i in range(len(weeks)):
        week = weeks[i]
        for j in range(len(week)):
            d = week[j]
            day2xy[d] = (j, i+1)
            t = day2text.get(d, '')
            format = "<b>%s</b>"
            if j in restdays: format = redFormat % format
            if t:
                p0 = Paragraph(format % d, bt)
                p1 = Paragraph(format % t, bt)
                week[j] = [p0, p1]

    # set table attributes
    red, black, pale = colors.red, colors.black, colors.lemonchiffon
    tableStyleAttributes = []
    app = tableStyleAttributes.append
    app(('ALIGN', (0, 0), (-1, -1), 'CENTER'))
    app(('VALIGN', (0, 0), (-1, -1), 'TOP'))
    app(('FONTSIZE', (0, 0), (-1, -1), 20))
    app(('GRID', (0, 0), (-1, -1), 1, black))
    for i in restdays:
        app(('TEXTCOLOR', (i, 0), (i, -1), red))
    for i in range(0, 7, 2):
        app(('BACKGROUND', (i, 0), (i, -1), pale))
    # for i in range(12, 21):
    #     app(('BACKGROUND', day2xy[str(i)], day2xy[str(i)], red))
    tableStyle = TableStyle(tableStyleAttributes)

    # make table
    rows = [weekdays] + weeks
    table = Table(rows, (WIDTH / 7.0,)*7, (1.5*cm,)*len(rows))
    table.setStyle(tableStyle)

    return table


def writePDF(year, imgDir, outPath, specialDays):
    "Create a PDF file with a 12 month calendar."

    nums = range(locale.MON_1, locale.MON_12+1)
    months = [getLtext(n) for n in nums]
    images = glob.glob(join("%s", "*.[jJ][pP][gG]") % imgDir)
    while len(images) < 12: images += images
    images = images[:12]
    specialDays = [sd.split(':') for sd in specialDays]

    story = []
    sp, pb = Spacer(0*cm, 1*cm), PageBreak()
    for i in range(12):
        img = Image(images[i], width=WIDTH, height=WIDTH*2/3.)
        p = Paragraph("%s %d" % (months[i], year), h1)
        s = [(m,d,tx) for (m,d,tx) in specialDays if int(m) == i + 1]
        dict = {}
        for m, d, tx in s: dict[str(eval(d))] = tx
        t = makeTable(year, i+1, day2text=dict)
        story += [img, sp, p, sp, t, pb]

    MyTemplate(outPath).build(story)


if __name__ == "__main__":
    year = datetime.datetime.now().year
    imgDir = "images"
    locName = 'de_de'
    outPath = None
    specialDays = []
    opts, args = getopt.getopt(sys.argv[1:], "y:i:l:o:s:")
    for k, v in opts:
        if k == '-y': year = int(v)
        if k == '-i': imgDir = v
        if k == '-l': locName = v
        if k == '-o': outPath = v
        if k == '-s': specialDays.append(v)
    loc = locale.locale_alias.get(locName)
    locale.setlocale(locale.LC_ALL, loc)
    if outPath is None: outPath = "calbum-%d.pdf" % year
    writePDF(year, imgDir, outPath, specialDays)