# Install necessary libraries (only needed in Colab)
!pip install reportlab pdf417gen Pillow requests

# Import necessary modules
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
from reportlab.lib import colors
from reportlab.lib.units import mm

from pdf417gen import encode, render_image
from PIL import Image
import os
import requests
from io import BytesIO

def generate_aamva_data(
    first_name,
    middle_name,
    last_name,
    license_number,
    address,
    city,
    state,
    zip_code,
    birth_date,
    issue_date,
    expiration_date,
    gender,
    eye_color,
    height,
    weight,
    height_unit='In',
    weight_unit='Lb',
    customer_id='',
    organ_donor='N',
    restrictions='NONE',
    endorsements='NONE',
    class_type='D'
):
    """
    Generates AAMVA-compliant data string for the barcode.
    """
    # AAMVA Header for version 1.0 (can be adjusted according to needs)
    data = ""
    data += "@"  # Start sentinel
    data += "ANSI "  # Compliance indicator
    data += "636026080002DL00410288ZA03290015DL"  # Issuer Identification Number and other header details (example values)
    
    # Data elements
    # Use fixed-length fields and proper codes as per AAMVA standards
    # Here is a simplified version; for full compliance, refer to AAMVA documentation
    data += f"DAQ{license_number}"          # Driver's license number
    data += f"DCS{last_name}"              # Surname
    data += f"DBA{expiration_date.replace('/', '')}"  # Document expiration date
    data += f"DBB{birth_date.replace('/', '')}"       # Date of Birth
    data += f"DAY{gender}"                  # Gender
    data += f"DBD{issue_date.replace('/', '')}"      # Document issue date
    data += f"DBH{height}{height_unit}"      # Height
    data += f"DBK{eye_color}"               # Eye color
    data += f"DBL{weight}{weight_unit}"      # Weight
    data += f"DCG{city}"                    # City
    data += f"DAJ{state}"                   # Jurisdiction code
    data += f"DAK{zip_code}"                # Postal code
    data += f"DCF{address}"                 # Street address
    data += f"DCI{first_name}"              # First name
    data += f"DC{middle_name}"             # Middle name (Note: Removed space after "DC")
    data += f"DCP{customer_id}"             # Customer ID (optional)
    data += f"DDH{organ_donor}"             # Organ donor
    data += f"DER{restrictions}"            # Restrictions
    data += f"DEE{endorsements}"            # Endorsements
    data += f"DEG{class_type}"              # Class
    # Add more fields as needed
    
    data += "}"  # End sentinel
    return data

def generate_drivers_license(
    name='Dyllun Levi Richard Garrett',
    address='12812 Southeast Harold Street',
    city='Portland',
    state='OR',
    zip_code='97236',
    license_number='2744164',
    birth_date='08/08/1994',
    issue_date='08/08/2019',
    expiration_date='08/08/2029',
    gender='1',  # 1=Male, 2=Female, 9=Not specified
    eye_color='BLU',  # Blue
    height='82',  # in inches
    weight='240',  # in lbs
    class_type='C',
    endorsements='NONE',
    restrictions='NONE',
    photo_path=None,  # No photo. Indicate blank area
    output_pdf='drivers_license_enhanced.pdf'
):
    # Split full name
    names = name.split()
    first_name = names[0]
    middle_name = ' '.join(names[1:-1]) if len(names) > 2 else ''
    last_name = names[-1]

    # Initialize canvas
    c = canvas.Canvas(output_pdf, pagesize=letter)
    width, height_page = letter  # width=612, height=792

    # -------------------- Front Page --------------------
    # Set background color
    c.setFillColorRGB(1, 1, 1)  # White background
    c.rect(0, 0, width, height_page, fill=True, stroke=False)

    # Add state seal/logo
    try:
        # Download Oregon state seal if not already downloaded
        logo_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Seal_of_Oregon.svg/512px-Seal_of_Oregon.svg.png"
        response = requests.get(logo_url)
        img = Image.open(BytesIO(response.content))
        img = img.convert("RGBA")
        
        # Resize the logo as needed
        img = img.resize((100, 100), Image.ANTIALIAS)
        logo_buffer = BytesIO()
        img.save(logo_buffer, format='PNG')
        logo_buffer.seek(0)
        logo = ImageReader(logo_buffer)
        
        c.drawImage(logo, 50, height_page - 120, width=100, height=100, mask='auto')
    except Exception as e:
        print(f"Error loading logo: {e}")

    # Add Title
    c.setFont("Helvetica-Bold", 20)
    c.setFillColor(colors.darkblue)
    c.drawString(170, height_page - 80, "State of Oregon")

    c.setFont("Helvetica-Bold", 16)
    c.setFillColor(colors.black)
    c.drawString(220, height_page - 100, "Driver's License")

    # Add Blank Photo Area
    c.setStrokeColor(colors.black)
    c.rect(width - 180, height_page - 260, 150, 200, stroke=1, fill=0)
    c.setFont("Helvetica", 10)
    c.drawCentredString(width - 105, height_page - 270, "Photo")

    # Add License Details
    c.setFont("Helvetica-Bold", 12)
    c.setFillColor(colors.black)
    start_x = 50
    start_y = height_page - 150

    details = [
        f"Name: {first_name} {middle_name} {last_name}",
        f"Address: {address}, {city}, {state} {zip_code}",
        f"License Number: {license_number}",
        f"Birth Date: {birth_date}",
        f"Issue Date: {issue_date}",
        f"Expiration Date: {expiration_date}",
        f"Class: {class_type}",
        f"Endorsements: {endorsements}",
        f"Restrictions: {restrictions}"
    ]

    for detail in details:
        c.drawString(start_x, start_y, detail)
        start_y -= 20  # Move down for next detail

    # Add Signature Line
    c.setFont("Helvetica", 12)
    c.drawString(start_x, start_y - 10, "Signature:")
    c.line(start_x + 70, start_y - 15, start_x + 250, start_y - 15)

    # Add Microtext or Security Features
    c.setFont("Helvetica-Oblique", 8)
    c.setFillColor(colors.grey)
    c.drawString(50, 40, "This is a computer-generated license and is not valid for official use.")

    # -------------------- Back Page --------------------
    c.showPage()  # Create a new page for the back

    # Set background color
    c.setFillColorRGB(1, 1, 1)  # White background
    c.rect(0, 0, width, height_page, fill=True, stroke=False)

    # Add Instructions or Security Text
    c.setFont("Helvetica", 10)
    c.setFillColor(colors.black)
    c.drawString(50, height_page - 50, "Do not alter or tamper with this document.")

    # Generate AAMVA Compliant Data
    aamva_data = generate_aamva_data(
        first_name=first_name,
        middle_name=middle_name,
        last_name=last_name,
        license_number=license_number,
        address=address,
        city=city,
        state=state,
        zip_code=zip_code,
        birth_date=birth_date,
        issue_date=issue_date,
        expiration_date=expiration_date,
        gender=gender,
        eye_color=eye_color,
        height=height,
        weight=weight,
        restrictions=restrictions,
        endorsements=endorsements,
        class_type=class_type
    )

    # Generate PDF417 Barcode
    try:
        barcode = encode(aamva_data, columns=6, security_level=5)
        barcode_image = render_image(barcode, scale=3, ratio=3, padding=5, fg_color="black", bg_color="white")
        
        # Convert the barcode PIL image to an in-memory object
        barcode_buffer = BytesIO()
        barcode_image.save(barcode_buffer, format='PNG')
        barcode_buffer.seek(0)
        barcode_image_reader = ImageReader(barcode_buffer)

        # Add Barcode to Back Page
        c.drawImage(barcode_image_reader, 50, height_page - 300, width=500, height=100)
    except Exception as e:
        print(f"Error generating barcode: {e}")

    # Add Note
    c.setFont("Helvetica-Oblique", 8)
    c.setFillColor(colors.grey)
    c.drawString(50, height_page - 320, "The barcode above contains encoded license information compliant with AAMVA standards.")

    # Add Oregon State Seal or Additional Elements if desired
    try:
        # Reuse the logo on the back if desired
        c.drawImage(logo, width - 150, height_page - 150, width=100, height=100, mask='auto')
    except Exception as e:
        print(f"Error adding logo on back: {e}")

    # Final Security Text
    c.setFont("Helvetica-Oblique", 8)
    c.setFillColor(colors.grey)
    c.drawString(50, 30, "This document is electronically verified and encrypted.")

    # Save the PDF
    c.save()

    # Provide download link if in Colab
    try:
        from google.colab import files
        files.download(output_pdf)
    except ImportError:
        print(f"PDF generated: {output_pdf}")

# Example usage
generate_drivers_license()