"""Original AdaPDF printables. Content/artwork: CC0 1.0.
Run with Python, reportlab and pypdf. No network or external artwork is used.
Example: python build-round-one-printables.py --printables-dir output/printables --size-dir output/pdf-size
"""
import argparse
import json
from pathlib import Path
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4, letter, landscape
from reportlab.lib.colors import HexColor, black
from reportlab.lib.units import mm
from pypdf import PdfReader

INK = HexColor('#203E48')
MUTED = HexColor('#53636A')
LINE = HexColor('#BAC6CA')


def new_pdf(path, size, title):
    c = canvas.Canvas(str(path), pagesize=size, pageCompression=1, invariant=1)
    c.setTitle(title)
    c.setAuthor('AdaPDF - original CC0 printable')
    c.setSubject('Original printable. No personal data. Not calibrated for optical mark recognition.')
    return c


def label(c, x, y, text, size=10, font='Helvetica', color=INK):
    c.setFillColor(color)
    c.setFont(font, size)
    c.drawString(x, y, text)


def header(c, width, height, eyebrow, title, subtitle):
    label(c, 14*mm, height-16*mm, eyebrow, 8, 'Helvetica-Bold', MUTED)
    label(c, 14*mm, height-29*mm, title, 25, 'Helvetica-Bold')
    label(c, 14*mm, height-37*mm, subtitle, 9, color=MUTED)
    c.setStrokeColor(INK)
    c.setLineWidth(.8)
    c.line(14*mm, height-41*mm, width-14*mm, height-41*mm)


def blank(path, size):
    c = new_pdf(path, size, 'Blank paper')
    c.showPage()
    c.save()


def tracker(path, size):
    width, height = landscape(size)
    c = new_pdf(path, (width, height), 'Monthly habit tracker')
    header(c, width, height, 'MONTHLY PLANNER', 'Small steps, one day at a time', 'Write a habit in each row. Mark completed days. Leave days outside your month empty.')
    label(c, 14*mm, height-51*mm, 'MONTH / YEAR', 8, 'Helvetica-Bold')
    c.setStrokeColor(LINE)
    c.line(44*mm, height-52*mm, 102*mm, height-52*mm)
    label(c, 118*mm, height-51*mm, 'MY FOCUS', 8, 'Helvetica-Bold')
    c.line(143*mm, height-52*mm, width-14*mm, height-52*mm)
    left, top = 14*mm, height-61*mm
    habit_width = 61*mm
    day_width = (width-28*mm-habit_width)/31
    row_height = 9*mm
    c.setFillColor(HexColor('#EAF0F1'))
    c.rect(left, top-row_height, width-28*mm, row_height, fill=1, stroke=0)
    c.setLineWidth(.45)
    c.setStrokeColor(LINE)
    for row in range(11):
        c.line(left, top-row*row_height, width-14*mm, top-row*row_height)
    for column in range(33):
        x = left if column == 0 else left+habit_width+(column-1)*day_width
        c.line(x, top, x, top-10*row_height)
    label(c, left+3*mm, top-5.8*mm, 'HABIT', 8, 'Helvetica-Bold')
    c.setFont('Helvetica', 7)
    c.setFillColor(INK)
    for day in range(1, 32):
        c.drawCentredString(left+habit_width+(day-.5)*day_width, top-5.8*mm, str(day))
    label(c, left, top-10*row_height-9*mm, 'WHAT HELPED THIS MONTH?', 8, 'Helvetica-Bold')
    for row in range(3):
        y = top-10*row_height-(14+7*row)*mm
        c.line(left, y, width-14*mm, y)
    label(c, 14*mm, 10*mm, 'Original AdaPDF printable | CC0 | Print in landscape at Actual size / 100%', 7, color=MUTED)
    c.showPage()
    c.save()


def answer_sheet(path, size):
    width, height = size
    c = new_pdf(path, size, 'Generic 50-question answer sheet')
    header(c, width, height, 'PRACTICE WORKSHEET', '50-question answer sheet', 'Choose one answer per row. This sheet is for practice and manual checking.')
    label(c, 14*mm, height-51*mm, 'NAME', 8, 'Helvetica-Bold')
    c.setStrokeColor(LINE)
    c.line(28*mm, height-52*mm, 105*mm, height-52*mm)
    label(c, 115*mm, height-51*mm, 'DATE', 8, 'Helvetica-Bold')
    c.line(128*mm, height-52*mm, width-14*mm, height-52*mm)
    label(c, 14*mm, height-61*mm, 'SUBJECT / PRACTICE SET', 8, 'Helvetica-Bold')
    c.line(62*mm, height-62*mm, width-14*mm, height-62*mm)
    top = height-78*mm
    column_width = (width-36*mm)/2
    for column in range(2):
        left = 14*mm+column*(column_width+8*mm)
        label(c, left, top, 'QUESTION', 7, 'Helvetica-Bold')
        for option in range(4):
            x = left+29*mm+option*12*mm
            c.setFillColor(INK)
            c.setFont('Helvetica-Bold', 8)
            c.drawCentredString(x, top, chr(65+option))
        for row in range(25):
            y = top-(row+1)*6.2*mm
            label(c, left+4*mm, y-1*mm, str(column*25+row+1), 9)
            c.setStrokeColor(MUTED)
            c.setLineWidth(.65)
            for option in range(4):
                c.circle(left+29*mm+option*12*mm, y, 2.15*mm, stroke=1, fill=0)
    label(c, 14*mm, 18*mm, 'Not calibrated for an OMR system. Check your instructor\'s required form before an exam.', 8, color=MUTED)
    label(c, 14*mm, 10*mm, 'Original AdaPDF printable | CC0 | Print at Actual size / 100%', 7, color=MUTED)
    c.showPage()
    c.save()


def size_control(path, size):
    c = new_pdf(path, size, 'Same content, different paper')
    c.setAuthor('AdaPDF')
    c.setSubject('Controlled page-size example: identical content, different MediaBox')
    label(c, 42, 700, 'Same content, different paper', 18, 'Helvetica-Bold')
    label(c, 42, 675, 'Changing paper dimensions is different from reducing file bytes.', 10)
    c.setStrokeColor(black)
    c.line(42, 655, 552, 655)
    c.showPage()
    c.save()


def inspect(path):
    reader = PdfReader(path)
    return {'file': path.name, 'bytes': path.stat().st_size, 'pages': len(reader.pages), 'widthMm': round(float(reader.pages[0].mediabox.width)/mm, 2), 'heightMm': round(float(reader.pages[0].mediabox.height)/mm, 2), 'textCharacters': len(reader.pages[0].extract_text())}


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--printables-dir', type=Path, default=Path('printable-output'))
    parser.add_argument('--size-dir', type=Path, default=Path('page-size-output'))
    args = parser.parse_args()
    args.printables_dir.mkdir(parents=True, exist_ok=True)
    args.size_dir.mkdir(parents=True, exist_ok=True)
    for name, size in [('a4', A4), ('letter', letter)]:
        blank(args.printables_dir/f'blank-{name}.pdf', size)
        tracker(args.printables_dir/f'monthly-habit-tracker-{name}.pdf', size)
        answer_sheet(args.printables_dir/f'answer-sheet-50-{name}.pdf', size)
        size_control(args.size_dir/f'same-content-{name}.pdf', size)
    for folder in [args.printables_dir, args.size_dir]:
        manifest = [inspect(path) for path in sorted(folder.glob('*.pdf'))]
        for record in manifest:
            assert record['pages'] == 1
            if record['file'].startswith('blank-'):
                assert record['textCharacters'] == 0
            else:
                assert record['textCharacters'] > 50
        (folder/'measurements.json').write_text(json.dumps(manifest, indent=2)+'\n', encoding='utf-8')
        print(json.dumps(manifest, indent=2))


if __name__ == '__main__':
    main()
