#!/usr/bin/env python3
"""
Pagination Example with PageBreak

This example demonstrates:
- Using PageBreak to force content onto new pages
- Multi-page document layout with automatic page creation
- Different content types across multiple pages
- Page numbering and document flow
- Combining text, images, and tables across pages

This shows how to create multi-page documents with explicit page breaks.
"""

import sys
from pathlib import Path
from PIL import Image, ImageDraw

# Add pyWebLayout to path
sys.path.insert(0, str(Path(__file__).parent.parent))

from pyWebLayout.concrete.page import Page
from pyWebLayout.style.page_style import PageStyle
from pyWebLayout.style.fonts import Font
from pyWebLayout.abstract.inline import Word
from pyWebLayout.abstract.block import Paragraph, PageBreak, Image as AbstractImage
from pyWebLayout.layout.document_layouter import DocumentLayouter


def create_sample_paragraph(text: str, font_size: int = 14) -> Paragraph:
    """Create a paragraph from plain text."""
    font = Font(font_size=font_size, colour=(50, 50, 50))
    paragraph = Paragraph(style=font)
    for word in text.split():
        paragraph.add_word(Word(word, font))
    return paragraph


def create_title_paragraph(text: str) -> Paragraph:
    """Create a title paragraph with larger font."""
    font = Font(font_size=24, colour=(0, 0, 100), weight='bold')
    paragraph = Paragraph(style=font)
    for word in text.split():
        paragraph.add_word(Word(word, font))
    return paragraph


def create_heading_paragraph(text: str) -> Paragraph:
    """Create a heading paragraph."""
    font = Font(font_size=18, colour=(50, 50, 100), weight='bold')
    paragraph = Paragraph(style=font)
    for word in text.split():
        paragraph.add_word(Word(word, font))
    return paragraph


def create_placeholder_image(width: int, height: int, label: str) -> AbstractImage:
    """Create a placeholder image for demonstration."""
    img = Image.new('RGB', (width, height), (200, 220, 240))
    draw = ImageDraw.Draw(img)

    # Draw border
    draw.rectangle([0, 0, width-1, height-1], outline=(100, 120, 140), width=2)

    # Add label
    text_bbox = draw.textbbox((0, 0), label)
    text_width = text_bbox[2] - text_bbox[0]
    text_height = text_bbox[3] - text_bbox[1]
    text_x = (width - text_width) // 2
    text_y = (height - text_height) // 2
    draw.text((text_x, text_y), label, fill=(80, 80, 120))

    return AbstractImage(source=img)


def create_example_document_with_pagebreaks():
    """
    Example: Multi-page document with explicit page breaks.

    This demonstrates how PageBreak forces content onto new pages.
    """
    print("\n  Creating multi-page document with PageBreaks...")

    # Define common page style
    page_style = PageStyle(
        border_width=2,
        border_color=(100, 100, 150),
        padding=(30, 40, 30, 40),
        background_color=(255, 255, 255),
        line_spacing=6
    )

    # Create document content with page breaks
    content = [
        # Page 1: Title and Introduction
        create_title_paragraph("Multi-Page Document Example"),
        create_sample_paragraph(
            "This document demonstrates how to use PageBreak elements to control "
            "document pagination. Each PageBreak forces subsequent content to start "
            "on a new page, allowing you to structure multi-page documents precisely."
        ),
        create_sample_paragraph(
            "Page breaks are particularly useful for creating chapters, sections, or "
            "ensuring that important content starts at the top of a fresh page rather "
            "than being split across page boundaries."
        ),

        # Force page break - next content will be on page 2
        PageBreak(),

        # Page 2: First Section
        create_heading_paragraph("Section 1: Text Content"),
        create_sample_paragraph(
            "This is the second page of our document. It starts with a clean break "
            "from the previous page, ensuring the section heading appears at the top."
        ),
        create_sample_paragraph(
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod "
            "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
            "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
            "commodo consequat."
        ),
        create_sample_paragraph(
            "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum "
            "dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non "
            "proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
        ),

        # Another page break
        PageBreak(),

        # Page 3: Images
        create_heading_paragraph("Section 2: Visual Content"),
        create_sample_paragraph(
            "This page contains image content, demonstrating that page breaks work "
            "correctly with different content types."
        ),
        create_placeholder_image(300, 200, "Figure 1: Sample Image"),
        create_sample_paragraph("The image above is placed on this dedicated page."),

        # Final page break
        PageBreak(),

        # Page 4: Conclusion
        create_heading_paragraph("Conclusion"),
        create_sample_paragraph(
            "This final page demonstrates that you can create complex multi-page "
            "documents by strategically placing PageBreak elements in your content."
        ),
        create_sample_paragraph(
            "Key benefits of using PageBreak: 1) Control where pages start, "
            "2) Prevent awkward content splits, 3) Create professional-looking "
            "documents with proper sectioning, 4) Ensure important content gets "
            "visual prominence at page tops."
        ),
        create_sample_paragraph(
            "Thank you for reviewing this pagination example. Try experimenting "
            "with PageBreak placement to create your own multi-page documents!"
        ),
    ]

    # Layout the document across multiple pages
    pages = []
    current_page = Page(size=(600, 800), style=page_style)
    layouter = DocumentLayouter(current_page)

    for element in content:
        if isinstance(element, PageBreak):
            # Save current page and create a new one
            pages.append(current_page)
            current_page = Page(size=(600, 800), style=page_style)
            layouter = DocumentLayouter(current_page)
        elif isinstance(element, Paragraph):
            success, _, _ = layouter.layout_paragraph(element)
            if not success:
                # Page is full, create new page and retry
                pages.append(current_page)
                current_page = Page(size=(600, 800), style=page_style)
                layouter = DocumentLayouter(current_page)
                success, _, _ = layouter.layout_paragraph(element)
                if not success:
                    print("    WARNING: Content too large for page")
        elif isinstance(element, AbstractImage):
            success = layouter.layout_image(element)
            if not success:
                # Image doesn't fit, try on new page
                pages.append(current_page)
                current_page = Page(size=(600, 800), style=page_style)
                layouter = DocumentLayouter(current_page)
                success = layouter.layout_image(element)
                if not success:
                    print("    WARNING: Image too large for page")

    # Add the final page
    pages.append(current_page)

    print(f"    Created {len(pages)} pages")
    return pages


def create_auto_pagination_example():
    """
    Example: Document that automatically flows to multiple pages.

    This shows the difference between automatic pagination (when content
    doesn't fit) vs explicit PageBreak usage.
    """
    print("\n  Creating auto-paginated document (no explicit breaks)...")

    page_style = PageStyle(
        border_width=1,
        border_color=(150, 150, 150),
        padding=(20, 30, 20, 30),
        background_color=(250, 250, 250),
        line_spacing=5
    )

    # Create lots of content that will naturally overflow
    content = [
        create_heading_paragraph("Auto-Pagination Example"),
        create_sample_paragraph(
            "This document does NOT use PageBreak. Instead, it demonstrates how "
            "content automatically flows to new pages when the current page is full."
        ),
    ]

    # Add many paragraphs to force automatic page breaks
    for i in range(1, 11):
        content.append(
            create_sample_paragraph(
                f"Paragraph {i}: This is automatically laid out content. "
                f"When this paragraph doesn't fit on the current page, the layouter "
                f"will create a new page automatically. This is different from using "
                f"PageBreak which forces a new page regardless of available space. "
                f"Auto-pagination is useful for flowing content naturally."
            )
        )

    # Layout across pages
    pages = []
    current_page = Page(size=(500, 600), style=page_style)
    layouter = DocumentLayouter(current_page)

    for element in content:
        if isinstance(element, Paragraph):
            success, _, _ = layouter.layout_paragraph(element)
            if not success:
                # Auto page break - content didn't fit
                pages.append(current_page)
                current_page = Page(size=(500, 600), style=page_style)
                layouter = DocumentLayouter(current_page)
                layouter.layout_paragraph(element)

    pages.append(current_page)

    print(f"    Auto-created {len(pages)} pages")
    return pages


def add_page_numbers(pages, start_number: int = 1):
    """Add page numbers to rendered pages."""
    numbered_pages = []
    font = Font(font_size=10, colour=(100, 100, 100))

    for i, page in enumerate(pages, start=start_number):
        # Render the page
        img = page.render()
        draw = ImageDraw.Draw(img)

        # Add page number at bottom center
        page_text = f"Page {i}"
        bbox = draw.textbbox((0, 0), page_text)
        text_width = bbox[2] - bbox[0]
        x = (img.size[0] - text_width) // 2
        y = img.size[1] - 20

        draw.text((x, y), page_text, fill=(100, 100, 100))
        numbered_pages.append(img)

    return numbered_pages


def combine_pages_vertically(pages, title: str = ""):
    """Combine multiple pages into a vertical strip."""
    if not pages:
        return None

    padding = 20
    title_height = 40 if title else 0

    # Calculate dimensions
    page_width = pages[0].size[0]
    page_height = pages[0].size[1]

    total_width = page_width + 2 * padding
    total_height = len(pages) * (page_height + padding) + padding + title_height

    # Create combined image
    combined = Image.new('RGB', (total_width, total_height), (240, 240, 240))
    draw = ImageDraw.Draw(combined)

    # Draw title if provided
    if title:
        from PIL import ImageFont
        try:
            title_font = ImageFont.truetype(
                "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 16
            )
        except:
            title_font = ImageFont.load_default()

        bbox = draw.textbbox((0, 0), title, font=title_font)
        text_width = bbox[2] - bbox[0]
        title_x = (total_width - text_width) // 2
        draw.text((title_x, 10), title, fill=(50, 50, 50), font=title_font)

    # Place pages vertically
    y_offset = title_height + padding
    for page_img in pages:
        combined.paste(page_img, (padding, y_offset))
        y_offset += page_height + padding

    return combined


def main():
    """Demonstrate pagination with PageBreak."""
    print("Pagination Example with PageBreak")
    print("=" * 50)

    # Example 1: Explicit page breaks
    pages1 = create_example_document_with_pagebreaks()
    rendered_pages1 = add_page_numbers(pages1)
    combined1 = combine_pages_vertically(
        rendered_pages1,
        "Example 1: Explicit PageBreak Usage"
    )

    # Example 2: Auto pagination
    pages2 = create_auto_pagination_example()
    rendered_pages2 = add_page_numbers(pages2)
    combined2 = combine_pages_vertically(
        rendered_pages2,
        "Example 2: Automatic Pagination"
    )

    # Save outputs
    output_dir = Path("docs/images")
    output_dir.mkdir(parents=True, exist_ok=True)

    output_path1 = output_dir / "example_08_pagination_explicit.png"
    output_path2 = output_dir / "example_08_pagination_auto.png"

    combined1.save(output_path1)
    combined2.save(output_path2)

    print("\n✓ Example completed!")
    print(f"  Output 1 saved to: {output_path1}")
    print(f"    - {len(pages1)} pages with explicit PageBreaks")
    print(f"  Output 2 saved to: {output_path2}")
    print(f"    - {len(pages2)} pages with auto-pagination")

    return combined1, combined2


if __name__ == "__main__":
    main()
