///|
/// SVG Rendering Integration for Sixel
/// Connects the SVG module to the Sixel rendering pipeline

///|
/// Convert SVG Color to sixel Color
fn svg_color_to_sixel(c : @svg.Color) -> Color {
  { r: c.r, g: c.g, b: c.b }
}

///|
/// Render an SVG scene to a Framebuffer
pub fn render_svg_scene(
  scene : @svg.Scene,
  fb : Framebuffer,
  palette : DynamicPalette,
) -> Unit {
  // Create pixel setter that integrates with the palette
  let setter : @svg.PixelSetter = {
    set: fn(x, y, color) {
      if x >= 0 && x < fb.width && y >= 0 && y < fb.height {
        let sixel_color = svg_color_to_sixel(color)
        let idx = palette.get_or_add(sixel_color)
        fb.set_pixel(x, y, idx)
      }
    },
  }
  let ctx = @svg.RenderContext::new(setter, fb.width, fb.height)
  scene.render(ctx)
}

///|
/// Render an SVG scene to Sixel string
pub fn render_svg_to_sixel(
  scene : @svg.Scene,
  width : Int,
  height : Int,
) -> String {
  let fb = Framebuffer::new(width, height)
  let palette = DynamicPalette::new()
  // Fill with white background
  fb.fill_rect(0, 0, width, height, 0)
  // Render SVG
  render_svg_scene(scene, fb, palette)
  // Convert to Sixel
  to_sixel_dynamic(fb, palette)
}

///|
/// Render an SVGNode directly to Sixel string
pub fn render_svg_node_to_sixel(
  node : @svg.SVGNode,
  width : Int,
  height : Int,
) -> String {
  let scene = @svg.Scene::new(node)
  render_svg_to_sixel(scene, width, height)
}

///|
/// Render an SVG path string to Sixel string
pub fn render_svg_path_to_sixel(
  path_data : String,
  fill_color : Color?,
  stroke_color : Color?,
  width : Int,
  height : Int,
) -> String {
  let commands = @svg.parse_path(path_data)
  let node = @svg.SVGNode::new(@svg.Path(commands~))
  match fill_color {
    Some(c) => node.fill = @svg.SolidColor(@svg.Color::rgb(c.r, c.g, c.b))
    None => node.fill = @svg.None
  }
  match stroke_color {
    Some(c) =>
      node.stroke = {
        paint: @svg.SolidColor(@svg.Color::rgb(c.r, c.g, c.b)),
        width: 1.0,
        linecap: @svg.Butt,
        linejoin: @svg.Miter,
        miterlimit: 4.0,
        dasharray: None,
        dashoffset: 0.0,
      }
    None => ()
  }
  render_svg_node_to_sixel(node, width, height)
}

///|
/// Render an SVG scene with camera to a Framebuffer
pub fn render_svg_scene_with_camera(
  scene : @svg.Scene,
  fb : Framebuffer,
  palette : DynamicPalette,
  camera : @svg.Camera,
) -> Unit {
  let setter : @svg.PixelSetter = {
    set: fn(x, y, color) {
      if x >= 0 && x < fb.width && y >= 0 && y < fb.height {
        let sixel_color = svg_color_to_sixel(color)
        let idx = palette.get_or_add(sixel_color)
        fb.set_pixel(x, y, idx)
      }
    },
  }
  let ctx = @svg.RenderContext::for_camera(setter, camera)
  scene.render_with_camera(ctx, camera)
}

///|
/// Render an SVG scene with camera to Sixel string
pub fn render_svg_to_sixel_with_camera(
  scene : @svg.Scene,
  camera : @svg.Camera,
) -> String {
  let fb = Framebuffer::new(camera.viewport_width, camera.viewport_height)
  let palette = DynamicPalette::new()
  // Fill with white background
  fb.fill_rect(0, 0, camera.viewport_width, camera.viewport_height, 0)
  // Create pixel setter
  let setter : @svg.PixelSetter = {
    set: fn(x, y, color) {
      if x >= 0 && x < fb.width && y >= 0 && y < fb.height {
        let sixel_color = svg_color_to_sixel(color)
        let idx = palette.get_or_add(sixel_color)
        fb.set_pixel(x, y, idx)
      }
    },
  }
  // Create render context with camera
  let ctx = @svg.RenderContext::for_camera(setter, camera)
  scene.render_with_camera(ctx, camera)
  // Convert to Sixel
  to_sixel_dynamic(fb, palette)
}

///|
/// Create a simple SVG demo scene
pub fn create_svg_demo_scene() -> @svg.Scene {
  // Create some shapes
  let rect1 = @svg.rect("rect1", 10.0, 10.0, 50.0, 30.0)
  rect1.fill = @svg.SolidColor(@svg.Color::rgb(255, 100, 100))
  rect1.stroke = {
    paint: @svg.SolidColor(@svg.Color::black()),
    width: 2.0,
    linecap: @svg.Butt,
    linejoin: @svg.Miter,
    miterlimit: 4.0,
    dasharray: None,
    dashoffset: 0.0,
  }
  let circle1 = @svg.circle("circle1", 100.0, 30.0, 20.0)
  circle1.fill = @svg.SolidColor(@svg.Color::rgb(100, 100, 255))
  circle1.stroke = {
    paint: @svg.SolidColor(@svg.Color::black()),
    width: 1.0,
    linecap: @svg.Butt,
    linejoin: @svg.Miter,
    miterlimit: 4.0,
    dasharray: None,
    dashoffset: 0.0,
  }
  let line1 = @svg.line("line1", 10.0, 60.0, 140.0, 60.0)
  line1.stroke = {
    paint: @svg.SolidColor(@svg.Color::rgb(0, 150, 0)),
    width: 3.0,
    linecap: @svg.Butt,
    linejoin: @svg.Miter,
    miterlimit: 4.0,
    dasharray: None,
    dashoffset: 0.0,
  }
  // Create a path (simple triangle)
  let path1 = @svg.path("path1", "M 70 70 L 100 100 L 40 100 Z")
  path1.fill = @svg.SolidColor(@svg.Color::rgb(255, 200, 0))
  path1.stroke = {
    paint: @svg.SolidColor(@svg.Color::black()),
    width: 1.0,
    linecap: @svg.Butt,
    linejoin: @svg.Miter,
    miterlimit: 4.0,
    dasharray: None,
    dashoffset: 0.0,
  }
  // Group them
  let root = @svg.group("root", [rect1, circle1, line1, path1])
  @svg.Scene::new(root)
}