/**
 * GAL Test Scenarios Implementation
 *
 * Uses KiCad's GAL API to render test patterns.
 * These serve as baselines for WEBGL_GAL visual regression testing.
 *
 * This file contains the original 11 scenarios (0-10).
 * Additional scenarios are in separate files:
 * - scenario_bezier_curves.cpp (11)
 * - scenario_arc_segments.cpp (12)
 * - scenario_segment_chain.cpp (13)
 * - scenario_group_caching.cpp (14)
 * - scenario_polylines_multi.cpp (15)
 * - scenario_hole_walls.cpp (16)
 * - scenario_grid_native.cpp (17)
 * - scenario_cursor_native.cpp (18)
 * - scenario_render_targets.cpp (19)
 * - scenario_screen_transform.cpp (20)
 * - scenario_clear_colors.cpp (21)
 * - scenario_depth_testing.cpp (22)
 * - scenario_negative_mode.cpp (23)
 * - scenario_text_attrs.cpp (24)
 * - scenario_glyphs.cpp (25)
 * - scenario_bitmap.cpp (26)
 * - scenario_transform.cpp (27)
 */

#include "gal_test_scenarios.h"
#include "kicad_stubs.h"  // For COLOR4D, VECTOR2D, EDA_ANGLE

// Include GAL header for the actual class definition
#include <gal/graphics_abstraction_layer.h>

#include <cmath>
#include <vector>
#include <deque>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

namespace GALTest {

// Import KIGFX types
using KIGFX::COLOR4D;
using KIGFX::GAL;

// Forward declarations for scenarios in separate files
void RenderBezierCurves(GAL* gal, int width, int height);
void RenderArcSegments(GAL* gal, int width, int height);
void RenderSegmentChain(GAL* gal, int width, int height);
void RenderGroupCaching(GAL* gal, int width, int height);
void RenderPolylinesMulti(GAL* gal, int width, int height);
void RenderHoleWalls(GAL* gal, int width, int height);
void RenderGridNative(GAL* gal, int width, int height);
void RenderCursorNative(GAL* gal, int width, int height);
void RenderRenderTargets(GAL* gal, int width, int height);
void RenderScreenTransform(GAL* gal, int width, int height);
void RenderClearColors(GAL* gal, int width, int height);
void RenderDepthTesting(GAL* gal, int width, int height);
void RenderNegativeMode(GAL* gal, int width, int height);
void RenderTextAttrs(GAL* gal, int width, int height);
void RenderGlyphs(GAL* gal, int width, int height);
void RenderBitmap(GAL* gal, int width, int height);
void RenderTransformAPI(GAL* gal, int width, int height);

// Scenario names - original 11 + 17 new scenarios
static const char* SCENARIO_NAMES[] = {
    // Original scenarios (0-10)
    "basic-lines",
    "line-widths",
    "circles",
    "arcs",
    "rectangles",
    "polygons",
    "alpha-blending",
    "transforms",
    "grid-cursor",
    "segments",
    "complex-scene",
    // New scenarios (11-23) - defined in separate files
    "bezier-curves",
    "arc-segments",
    "segment-chain",
    "group-caching",
    "polylines-multi",
    "hole-walls",
    "grid-native",
    "cursor-native",
    "render-targets",
    "screen-transform",
    "clear-colors",
    "depth-testing",
    "negative-mode",
    // Additional scenarios (24-27) - defined in separate files
    "text-attrs",
    "glyphs",
    "bitmap",
    "transform-api"
};

static const int SCENARIO_COUNT = sizeof(SCENARIO_NAMES) / sizeof(SCENARIO_NAMES[0]);

int GetScenarioCount() {
    return SCENARIO_COUNT;
}

const char* GetScenarioName(int index) {
    if (index >= 0 && index < SCENARIO_COUNT) {
        return SCENARIO_NAMES[index];
    }
    return "unknown";
}

//=============================================================================
// Scenario Implementations using GAL API
//=============================================================================

// Scenario 0: Basic lines
static void RenderBasicLines(KIGFX::GAL* gal, int width, int height) {
    double cx = width / 2.0;
    double cy = height / 2.0;
    double len = std::min(width, height) * 0.35;

    gal->SetLineWidth(1.0);
    gal->SetIsFill(false);
    gal->SetIsStroke(true);

    // Horizontal line (red)
    gal->SetStrokeColor(COLOR4D(1.0, 0.2, 0.2, 1.0));
    gal->DrawLine(VECTOR2D(cx - len, cy), VECTOR2D(cx + len, cy));

    // Vertical line (green)
    gal->SetStrokeColor(COLOR4D(0.2, 1.0, 0.2, 1.0));
    gal->DrawLine(VECTOR2D(cx, cy - len), VECTOR2D(cx, cy + len));

    // Diagonal lines (blue, yellow)
    gal->SetStrokeColor(COLOR4D(0.2, 0.2, 1.0, 1.0));
    gal->DrawLine(VECTOR2D(cx - len, cy - len), VECTOR2D(cx + len, cy + len));

    gal->SetStrokeColor(COLOR4D(1.0, 1.0, 0.2, 1.0));
    gal->DrawLine(VECTOR2D(cx - len, cy + len), VECTOR2D(cx + len, cy - len));

    // Radial lines (white)
    gal->SetStrokeColor(COLOR4D(0.8, 0.8, 0.8, 1.0));
    for (int i = 0; i < 8; i++) {
        double angle = M_PI * i / 8;
        double x = cos(angle) * len * 0.8;
        double y = sin(angle) * len * 0.8;
        gal->DrawLine(VECTOR2D(cx + x * 0.3, cy + y * 0.3), VECTOR2D(cx + x, cy + y));
    }
}

// Scenario 1: Line widths (tests SetLineWidth and SetMinLineWidth)
static void RenderLineWidths(KIGFX::GAL* gal, int width, int height) {
    double widths[] = {0.5, 1.0, 2.0, 3.0, 5.0, 8.0, 12.0};
    int count = sizeof(widths) / sizeof(widths[0]);

    double margin = 50.0;
    double spacing = (height - 2 * margin) / (count + 3);  // +3 for min width demos

    gal->SetIsFill(false);
    gal->SetIsStroke(true);

    // First section: Normal line widths
    for (int i = 0; i < count; i++) {
        double y = margin + (i + 1) * spacing;

        // Color gradient
        double t = (double)i / (count - 1);
        gal->SetStrokeColor(COLOR4D(1.0 - t * 0.5, 0.3 + t * 0.4, 0.2 + t * 0.6, 1.0));
        gal->SetLineWidth(widths[i]);
        gal->DrawLine(VECTOR2D(margin, y), VECTOR2D(width * 0.45, y));
    }

    // Second section: Test SetMinLineWidth
    // Lines with width 0.5 but different min line widths
    double baseY = margin + (count + 1) * spacing;

    // Very thin line (0.1) without min width - may be invisible
    gal->SetMinLineWidth(0.0);  // No minimum
    gal->SetLineWidth(0.1);
    gal->SetStrokeColor(COLOR4D(1.0, 0.3, 0.3, 1.0));
    gal->DrawLine(VECTOR2D(width * 0.55, baseY), VECTOR2D(width - margin, baseY));

    // Very thin line (0.1) with min width 1.0 - should be visible
    baseY += spacing;
    gal->SetMinLineWidth(1.0);  // Minimum 1 pixel
    gal->SetLineWidth(0.1);
    gal->SetStrokeColor(COLOR4D(0.3, 1.0, 0.3, 1.0));
    gal->DrawLine(VECTOR2D(width * 0.55, baseY), VECTOR2D(width - margin, baseY));

    // Very thin line (0.1) with min width 3.0 - should be thicker
    baseY += spacing;
    gal->SetMinLineWidth(3.0);  // Minimum 3 pixels
    gal->SetLineWidth(0.1);
    gal->SetStrokeColor(COLOR4D(0.3, 0.3, 1.0, 1.0));
    gal->DrawLine(VECTOR2D(width * 0.55, baseY), VECTOR2D(width - margin, baseY));

    // Reset min line width
    gal->SetMinLineWidth(0.0);
}

// Scenario 2: Circles
static void RenderCircles(KIGFX::GAL* gal, int width, int height) {
    double cx = width / 2.0;
    double cy = height / 2.0;

    // Filled circles
    gal->SetIsFill(true);
    gal->SetIsStroke(false);

    gal->SetFillColor(COLOR4D(0.8, 0.2, 0.2, 0.8));
    gal->DrawCircle(VECTOR2D(cx - 150, cy - 100), 60);

    gal->SetFillColor(COLOR4D(0.2, 0.8, 0.2, 0.8));
    gal->DrawCircle(VECTOR2D(cx, cy - 100), 80);

    gal->SetFillColor(COLOR4D(0.2, 0.2, 0.8, 0.8));
    gal->DrawCircle(VECTOR2D(cx + 150, cy - 100), 50);

    // Stroked circles
    gal->SetIsFill(false);
    gal->SetIsStroke(true);
    gal->SetLineWidth(2.0);

    gal->SetStrokeColor(COLOR4D(1.0, 0.5, 0.0, 1.0));
    gal->DrawCircle(VECTOR2D(cx - 150, cy + 100), 70);

    gal->SetStrokeColor(COLOR4D(0.0, 1.0, 1.0, 1.0));
    gal->DrawCircle(VECTOR2D(cx, cy + 100), 90);

    gal->SetStrokeColor(COLOR4D(1.0, 0.0, 1.0, 1.0));
    gal->DrawCircle(VECTOR2D(cx + 150, cy + 100), 55);

    // Concentric circles
    gal->SetStrokeColor(COLOR4D(0.6, 0.6, 0.6, 1.0));
    gal->SetLineWidth(1.0);
    for (double r = 20; r <= 200; r += 30) {
        gal->DrawCircle(VECTOR2D(cx, cy), r);
    }
}

// Scenario 3: Arcs
static void RenderArcs(KIGFX::GAL* gal, int width, int height) {
    double cx = width / 2.0;
    double cy = height / 2.0;
    double radius = std::min(width, height) * 0.25;

    gal->SetIsFill(false);
    gal->SetIsStroke(true);
    gal->SetLineWidth(3.0);

    // 90 degree arcs in each quadrant
    gal->SetStrokeColor(COLOR4D(1.0, 0.3, 0.3, 1.0));
    gal->DrawArc(VECTOR2D(cx, cy), radius,
                 EDA_ANGLE(0, DEGREES_T), EDA_ANGLE(90, DEGREES_T));

    gal->SetStrokeColor(COLOR4D(0.3, 1.0, 0.3, 1.0));
    gal->DrawArc(VECTOR2D(cx, cy), radius,
                 EDA_ANGLE(90, DEGREES_T), EDA_ANGLE(90, DEGREES_T));

    gal->SetStrokeColor(COLOR4D(0.3, 0.3, 1.0, 1.0));
    gal->DrawArc(VECTOR2D(cx, cy), radius,
                 EDA_ANGLE(180, DEGREES_T), EDA_ANGLE(90, DEGREES_T));

    gal->SetStrokeColor(COLOR4D(1.0, 1.0, 0.3, 1.0));
    gal->DrawArc(VECTOR2D(cx, cy), radius,
                 EDA_ANGLE(270, DEGREES_T), EDA_ANGLE(90, DEGREES_T));

    // Inner arcs
    gal->SetLineWidth(2.0);
    gal->SetStrokeColor(COLOR4D(0.8, 0.5, 0.8, 1.0));
    gal->DrawArc(VECTOR2D(cx, cy), radius * 0.6,
                 EDA_ANGLE(30, DEGREES_T), EDA_ANGLE(120, DEGREES_T));

    gal->SetStrokeColor(COLOR4D(0.5, 0.8, 0.8, 1.0));
    gal->DrawArc(VECTOR2D(cx, cy), radius * 0.6,
                 EDA_ANGLE(210, DEGREES_T), EDA_ANGLE(120, DEGREES_T));
}

// Scenario 4: Rectangles
static void RenderRectangles(KIGFX::GAL* gal, int width, int height) {
    double margin = 50.0;

    // Filled rectangles
    gal->SetIsFill(true);
    gal->SetIsStroke(false);

    gal->SetFillColor(COLOR4D(0.8, 0.2, 0.2, 0.9));
    gal->DrawRectangle(VECTOR2D(margin, margin), VECTOR2D(margin + 120, margin + 80));

    gal->SetFillColor(COLOR4D(0.2, 0.8, 0.2, 0.9));
    gal->DrawRectangle(VECTOR2D(margin + 140, margin), VECTOR2D(margin + 240, margin + 100));

    gal->SetFillColor(COLOR4D(0.2, 0.2, 0.8, 0.9));
    gal->DrawRectangle(VECTOR2D(margin + 260, margin), VECTOR2D(margin + 340, margin + 120));

    // Stroked rectangles
    gal->SetIsFill(false);
    gal->SetIsStroke(true);
    gal->SetLineWidth(2.0);

    gal->SetStrokeColor(COLOR4D(1.0, 0.5, 0.0, 1.0));
    gal->DrawRectangle(VECTOR2D(margin, height - margin - 100),
                       VECTOR2D(margin + 150, height - margin - 20));

    gal->SetStrokeColor(COLOR4D(0.0, 1.0, 1.0, 1.0));
    gal->DrawRectangle(VECTOR2D(margin + 170, height - margin - 110),
                       VECTOR2D(margin + 280, height - margin - 20));

    gal->SetStrokeColor(COLOR4D(1.0, 0.0, 1.0, 1.0));
    gal->DrawRectangle(VECTOR2D(margin + 300, height - margin - 90),
                       VECTOR2D(margin + 390, height - margin - 20));

    // Nested rectangles
    gal->SetLineWidth(1.0);
    double cx = width / 2.0;
    double cy = height / 2.0;
    for (int i = 0; i < 6; i++) {
        double t = (double)i / 5;
        gal->SetStrokeColor(COLOR4D(t, 0.5, 1.0 - t, 1.0));
        double size = 30 + i * 25;
        gal->DrawRectangle(VECTOR2D(cx - size, cy - size * 0.6),
                           VECTOR2D(cx + size, cy + size * 0.6));
    }
}

// Scenario 5: Polygons
static void RenderPolygons(KIGFX::GAL* gal, int width, int height) {
    double cx = width / 2.0;
    double cy = height / 2.0;

    // Triangle (filled)
    gal->SetIsFill(true);
    gal->SetIsStroke(false);
    gal->SetFillColor(COLOR4D(1.0, 0.3, 0.3, 0.8));

    std::deque<VECTOR2D> triangle = {
        VECTOR2D(cx - 200, cy - 50),
        VECTOR2D(cx - 130, cy - 50),
        VECTOR2D(cx - 165, cy - 120)
    };
    gal->DrawPolygon(triangle);

    // Square (filled)
    gal->SetFillColor(COLOR4D(0.3, 1.0, 0.3, 0.8));
    std::deque<VECTOR2D> square = {
        VECTOR2D(cx - 50, cy - 50),
        VECTOR2D(cx + 30, cy - 50),
        VECTOR2D(cx + 30, cy - 130),
        VECTOR2D(cx - 50, cy - 130)
    };
    gal->DrawPolygon(square);

    // Pentagon (filled)
    gal->SetFillColor(COLOR4D(0.3, 0.3, 1.0, 0.8));
    std::deque<VECTOR2D> pentagon;
    for (int i = 0; i < 5; i++) {
        double angle = -M_PI / 2 + 2 * M_PI * i / 5;
        pentagon.push_back(VECTOR2D(cx + 165 + cos(angle) * 50, cy - 90 + sin(angle) * 50));
    }
    gal->DrawPolygon(pentagon);

    // Star (stroked)
    gal->SetIsFill(false);
    gal->SetIsStroke(true);
    gal->SetLineWidth(2.0);
    gal->SetStrokeColor(COLOR4D(1.0, 0.8, 0.0, 1.0));

    std::deque<VECTOR2D> star;
    for (int i = 0; i < 10; i++) {
        double angle = -M_PI / 2 + M_PI * i / 5;
        double r = (i % 2 == 0) ? 60 : 30;
        star.push_back(VECTOR2D(cx + cos(angle) * r, cy + 80 + sin(angle) * r));
    }
    // Draw as polyline (closed)
    std::vector<VECTOR2D> starVec(star.begin(), star.end());
    starVec.push_back(star.front());  // Close the shape
    gal->DrawPolyline(starVec);

    // Hexagon (stroked)
    gal->SetStrokeColor(COLOR4D(0.8, 0.3, 0.8, 1.0));
    std::deque<VECTOR2D> hexagon;
    for (int i = 0; i < 6; i++) {
        double angle = M_PI * i / 3;
        hexagon.push_back(VECTOR2D(cx - 150 + cos(angle) * 45, cy + 80 + sin(angle) * 45));
    }
    std::vector<VECTOR2D> hexVec(hexagon.begin(), hexagon.end());
    hexVec.push_back(hexagon.front());  // Close the shape
    gal->DrawPolyline(hexVec);
}

// Scenario 6: Alpha blending
static void RenderAlphaBlending(KIGFX::GAL* gal, int width, int height) {
    double cx = width / 2.0;
    double cy = height / 2.0;

    gal->SetIsFill(true);
    gal->SetIsStroke(false);

    // Overlapping rectangles with different alphas
    gal->SetFillColor(COLOR4D(1.0, 0.0, 0.0, 0.5));
    gal->DrawRectangle(VECTOR2D(cx - 150, cy - 80), VECTOR2D(cx + 30, cy + 40));

    gal->SetFillColor(COLOR4D(0.0, 1.0, 0.0, 0.5));
    gal->DrawRectangle(VECTOR2D(cx - 60, cy - 80), VECTOR2D(cx + 120, cy + 40));

    gal->SetFillColor(COLOR4D(0.0, 0.0, 1.0, 0.5));
    gal->DrawRectangle(VECTOR2D(cx - 105, cy - 20), VECTOR2D(cx + 75, cy + 100));

    // Overlapping circles
    gal->SetFillColor(COLOR4D(1.0, 1.0, 0.0, 0.4));
    gal->DrawCircle(VECTOR2D(cx - 180, cy + 100), 60);

    gal->SetFillColor(COLOR4D(0.0, 1.0, 1.0, 0.4));
    gal->DrawCircle(VECTOR2D(cx - 130, cy + 100), 60);

    gal->SetFillColor(COLOR4D(1.0, 0.0, 1.0, 0.4));
    gal->DrawCircle(VECTOR2D(cx - 155, cy + 60), 60);

    // Alpha gradient
    for (int i = 0; i < 8; i++) {
        double alpha = 0.1 + i * 0.1;
        gal->SetFillColor(COLOR4D(0.5, 0.5, 0.5, alpha));
        gal->DrawRectangle(VECTOR2D(cx + 50 + i * 30, cy - 50),
                           VECTOR2D(cx + 75 + i * 30, cy + 50));
    }
}

// Scenario 7: Transforms (tests Translate, Rotate, Scale, Save/Restore)
// NOTE: Transform() with MATRIX3x3D doesn't work with OPENGL_GAL's shader pipeline
static void RenderTransforms(KIGFX::GAL* gal, int width, int height) {
    double cx = width / 2.0;
    double cy = height / 2.0;

    gal->SetIsFill(false);
    gal->SetIsStroke(true);
    gal->SetLineWidth(2.0);

    // Original (reference)
    gal->SetStrokeColor(COLOR4D(0.5, 0.5, 0.5, 1.0));
    gal->DrawRectangle(VECTOR2D(cx - 230, cy - 120), VECTOR2D(cx - 170, cy - 80));

    // Translated
    gal->Save();
    gal->Translate(VECTOR2D(100, 20));
    gal->SetStrokeColor(COLOR4D(1.0, 0.3, 0.3, 1.0));
    gal->DrawRectangle(VECTOR2D(cx - 230, cy - 120), VECTOR2D(cx - 170, cy - 80));
    gal->Restore();

    // Rotated
    gal->Save();
    gal->Translate(VECTOR2D(cx, cy - 80));
    gal->Rotate(30.0 * M_PI / 180.0);
    gal->SetStrokeColor(COLOR4D(0.3, 1.0, 0.3, 1.0));
    gal->DrawRectangle(VECTOR2D(-30, -20), VECTOR2D(30, 20));
    gal->Restore();

    // Scaled
    gal->Save();
    gal->Translate(VECTOR2D(cx + 120, cy - 80));
    gal->Scale(VECTOR2D(1.5, 0.8));
    gal->SetStrokeColor(COLOR4D(0.3, 0.3, 1.0, 1.0));
    gal->DrawRectangle(VECTOR2D(-30, -20), VECTOR2D(30, 20));
    gal->Restore();

    // Combined transforms
    gal->Save();
    gal->Translate(VECTOR2D(cx, cy + 80));
    gal->Rotate(45.0 * M_PI / 180.0);
    gal->Scale(VECTOR2D(1.2, 1.2));
    gal->SetStrokeColor(COLOR4D(1.0, 1.0, 0.3, 1.0));
    gal->DrawRectangle(VECTOR2D(-40, -25), VECTOR2D(40, 25));
    gal->Restore();

    // Nested transforms
    gal->Save();
    gal->Translate(VECTOR2D(cx - 150, cy + 100));
    gal->SetStrokeColor(COLOR4D(0.8, 0.4, 0.8, 1.0));
    gal->DrawCircle(VECTOR2D(0, 0), 30);

    gal->Save();
    gal->Rotate(60.0 * M_PI / 180.0);
    gal->Translate(VECTOR2D(50, 0));
    gal->SetStrokeColor(COLOR4D(0.4, 0.8, 0.8, 1.0));
    gal->DrawCircle(VECTOR2D(0, 0), 20);
    gal->Restore();

    gal->Restore();
}

// Scenario 8: Grid and cursor
static void RenderGridCursor(KIGFX::GAL* gal, int width, int height) {
    gal->SetIsFill(false);
    gal->SetIsStroke(true);

    // Grid
    gal->SetStrokeColor(COLOR4D(0.3, 0.3, 0.4, 0.5));
    gal->SetLineWidth(1.0);

    double gridSize = 40.0;
    for (double x = gridSize; x < width; x += gridSize) {
        gal->DrawLine(VECTOR2D(x, 0), VECTOR2D(x, height));
    }
    for (double y = gridSize; y < height; y += gridSize) {
        gal->DrawLine(VECTOR2D(0, y), VECTOR2D(width, y));
    }

    // Major grid
    gal->SetStrokeColor(COLOR4D(0.4, 0.4, 0.5, 0.7));
    double majorGridSize = 200.0;
    gal->SetLineWidth(2.0);
    for (double x = majorGridSize; x < width; x += majorGridSize) {
        gal->DrawLine(VECTOR2D(x, 0), VECTOR2D(x, height));
    }
    for (double y = majorGridSize; y < height; y += majorGridSize) {
        gal->DrawLine(VECTOR2D(0, y), VECTOR2D(width, y));
    }

    // Cursor (crosshair)
    double cx = width / 2.0;
    double cy = height / 2.0;
    double cursorSize = 30.0;

    gal->SetLineWidth(2.0);
    gal->SetStrokeColor(COLOR4D(1.0, 1.0, 1.0, 1.0));
    gal->DrawLine(VECTOR2D(cx - cursorSize, cy), VECTOR2D(cx + cursorSize, cy));
    gal->DrawLine(VECTOR2D(cx, cy - cursorSize), VECTOR2D(cx, cy + cursorSize));

    // Cursor circle
    gal->SetStrokeColor(COLOR4D(1.0, 1.0, 0.0, 0.8));
    gal->DrawCircle(VECTOR2D(cx, cy), cursorSize * 0.8);
}

// Scenario 9: Segments (thick lines with round caps)
static void RenderSegments(KIGFX::GAL* gal, int width, int height) {
    double margin = 80.0;

    // Horizontal segments with different widths
    double widths[] = {5.0, 10.0, 20.0, 30.0};
    int count = sizeof(widths) / sizeof(widths[0]);

    gal->SetIsFill(true);
    gal->SetIsStroke(false);

    for (int i = 0; i < count; i++) {
        double y = margin + i * 80;
        double w = widths[i];

        gal->SetFillColor(COLOR4D(0.3 + i * 0.2, 0.5, 0.8 - i * 0.15, 1.0));

        // DrawSegment draws a rounded segment
        gal->DrawSegment(VECTOR2D(margin, y), VECTOR2D(width - margin, y), w);
    }

    // Diagonal segment
    gal->SetFillColor(COLOR4D(1.0, 0.5, 0.2, 1.0));
    gal->DrawSegment(VECTOR2D(margin, height - margin),
                     VECTOR2D(width / 2.0, height - margin - 150), 15.0);
}

// Scenario 10: Complex scene (PCB-like, tests SetLayerDepth and AdvanceDepth)
static void RenderComplexScene(KIGFX::GAL* gal, int width, int height) {
    // Use layer depths to ensure proper z-ordering
    // Lower depth = closer to camera (drawn on top with GL_LESS)

    // Background "board" - deepest layer
    gal->SetLayerDepth(100);
    gal->SetIsFill(true);
    gal->SetIsStroke(false);
    gal->SetFillColor(COLOR4D(0.1, 0.3, 0.1, 1.0));
    gal->DrawRectangle(VECTOR2D(50, 50), VECTOR2D(width - 50, height - 50));

    // Traces (copper) - middle layer
    gal->SetLayerDepth(50);
    gal->SetIsFill(false);
    gal->SetIsStroke(true);
    gal->SetStrokeColor(COLOR4D(0.8, 0.6, 0.2, 1.0));
    gal->SetLineWidth(3.0);

    // Horizontal traces
    for (int i = 0; i < 5; i++) {
        double y = 100 + i * 100;
        gal->DrawLine(VECTOR2D(80, y), VECTOR2D(width - 80, y));
    }

    // Vertical traces
    for (int i = 0; i < 6; i++) {
        double x = 100 + i * 120;
        gal->DrawLine(VECTOR2D(x, 80), VECTOR2D(x, height - 80));
    }

    // Pads (circles) - above traces
    gal->SetLayerDepth(30);
    gal->SetIsFill(true);
    gal->SetIsStroke(false);
    gal->SetFillColor(COLOR4D(0.9, 0.7, 0.3, 1.0));
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 6; j++) {
            double x = 100 + j * 120;
            double y = 100 + i * 100;
            gal->DrawCircle(VECTOR2D(x, y), 15);
        }
    }

    // Holes - above pads
    gal->SetLayerDepth(20);
    gal->SetFillColor(COLOR4D(0.1, 0.1, 0.1, 1.0));
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 6; j++) {
            double x = 100 + j * 120;
            double y = 100 + i * 100;
            gal->DrawCircle(VECTOR2D(x, y), 5);
        }
    }

    // Component outline - top layer
    gal->SetLayerDepth(10);
    gal->SetIsFill(false);
    gal->SetIsStroke(true);
    gal->SetStrokeColor(COLOR4D(1.0, 1.0, 0.0, 1.0));
    gal->SetLineWidth(1.0);
    gal->DrawRectangle(VECTOR2D(width / 2 - 80, height / 2 - 40),
                       VECTOR2D(width / 2 + 80, height / 2 + 40));

    // Reference designator placeholder - topmost
    gal->SetLayerDepth(5);
    gal->SetStrokeColor(COLOR4D(1.0, 1.0, 1.0, 1.0));
    gal->DrawRectangle(VECTOR2D(width / 2 - 20, height / 2 - 15),
                       VECTOR2D(width / 2 + 20, height / 2 + 15));

    // Demonstrate AdvanceDepth() - auto-incrementing depth
    // Draw a stack of overlapping circles using AdvanceDepth
    gal->SetLayerDepth(80);  // Start at depth 80
    gal->SetIsFill(true);
    gal->SetIsStroke(false);

    // Each call to AdvanceDepth moves closer to camera (decrements depth)
    double stackX = width - 120;
    double stackY = height - 120;

    // First circle (deepest in stack)
    gal->SetFillColor(COLOR4D(0.8, 0.2, 0.2, 0.9));
    gal->DrawCircle(VECTOR2D(stackX, stackY), 35);
    gal->AdvanceDepth();  // Move closer to camera

    // Second circle
    gal->SetFillColor(COLOR4D(0.2, 0.8, 0.2, 0.9));
    gal->DrawCircle(VECTOR2D(stackX + 15, stackY - 10), 30);
    gal->AdvanceDepth();

    // Third circle
    gal->SetFillColor(COLOR4D(0.2, 0.2, 0.8, 0.9));
    gal->DrawCircle(VECTOR2D(stackX + 30, stackY - 20), 25);
    gal->AdvanceDepth();

    // Fourth circle (closest to camera)
    gal->SetFillColor(COLOR4D(0.8, 0.8, 0.2, 0.9));
    gal->DrawCircle(VECTOR2D(stackX + 45, stackY - 30), 20);
}

//=============================================================================
// Main dispatch function
//=============================================================================

void RenderScenario(KIGFX::GAL* gal, int index, int width, int height) {
    switch (index) {
        // Original scenarios (0-10) - defined in this file
        case 0: RenderBasicLines(gal, width, height); break;
        case 1: RenderLineWidths(gal, width, height); break;
        case 2: RenderCircles(gal, width, height); break;
        case 3: RenderArcs(gal, width, height); break;
        case 4: RenderRectangles(gal, width, height); break;
        case 5: RenderPolygons(gal, width, height); break;
        case 6: RenderAlphaBlending(gal, width, height); break;
        case 7: RenderTransforms(gal, width, height); break;
        case 8: RenderGridCursor(gal, width, height); break;
        case 9: RenderSegments(gal, width, height); break;
        case 10: RenderComplexScene(gal, width, height); break;
        // New scenarios (11-20) - defined in separate files
        case 11: RenderBezierCurves(gal, width, height); break;
        case 12: RenderArcSegments(gal, width, height); break;
        case 13: RenderSegmentChain(gal, width, height); break;
        case 14: RenderGroupCaching(gal, width, height); break;
        case 15: RenderPolylinesMulti(gal, width, height); break;
        case 16: RenderHoleWalls(gal, width, height); break;
        case 17: RenderGridNative(gal, width, height); break;
        case 18: RenderCursorNative(gal, width, height); break;
        case 19: RenderRenderTargets(gal, width, height); break;
        case 20: RenderScreenTransform(gal, width, height); break;
        case 21: RenderClearColors(gal, width, height); break;
        case 22: RenderDepthTesting(gal, width, height); break;
        case 23: RenderNegativeMode(gal, width, height); break;
        // Additional scenarios (24-27) - defined in separate files
        case 24: RenderTextAttrs(gal, width, height); break;
        case 25: RenderGlyphs(gal, width, height); break;
        case 26: RenderBitmap(gal, width, height); break;
        case 27: RenderTransformAPI(gal, width, height); break;
        default: break;
    }
}

}  // namespace GALTest
