// Test webcam display
var draw2d
var graphics
var os = use('os');
var input = use('input')
var json = use('json')
var surface = use('sdl3/surface')
input.watch($self)

// Create SDL video actor
var video_actor = use('sdl3/video');
var camera = use('camera')

var window_id = null;
var renderer_id = null;
var cam_id = null;
var cam_obj = null;
var cam_approved = false;
var webcam_texture = null;

// Handle camera events
$receiver(e => {
  if (e.type == 'camera_device_approved' && e.which == cam_id) {
    log.console("Camera approved!");
    cam_approved = true;
  } else if (e.type == 'camera_device_denied' && e.which == cam_id) {
    log.error("Camera access denied!");
    $stop();
  }
})

// Create window
send(video_actor, {
  kind: "window", 
  op: "create", 
  data: {
    title: "Webcam Test",
    width: 800,
    height: 600
  }
}, function(response) {
  if (response.error) {
    log.error("Failed to create window:", response.error);
    return;
  }
  
  window_id = response.id;
  log.console("Created window with id:", window_id);
  
  // Create renderer
  send(video_actor, {
    kind: "window", 
    op: "makeRenderer", 
    id: window_id
  }, function(response) {
    if (response.error) {
      log.error("Failed to create renderer:", response.error);
      return;
    }
    
    renderer_id = response.id;
    log.console("Created renderer with id:", renderer_id);
    
    // Configure draw2d and graphics
    draw2d = use('draw2d', video_actor, renderer_id)
    graphics = use('graphics', video_actor, renderer_id)
    
    // List available cameras
    var cameras = camera.list();
    if (length(cameras) == 0) {
      log.error("No cameras found!");
      log.console(cameras)
      $stop();
      return;
    }
    
    log.console("Found", length(cameras), "camera(s)");
    
    // Open the first camera
    cam_id = cameras[0];
    var cam_name = camera.name(cam_id);
    var cam_position = camera.position(cam_id);
    log.console("Opening camera:", cam_name, "Position:", cam_position);
    
    // Get supported formats and try to find a good one
    var formats = camera.supported_formats(cam_id);
    log.console("Camera supports", length(formats), "formats");
    
    // Look for a 640x480 format with preferred colorspace
    var preferred_format = null;
    for (var i = 0; i < length(formats); i++) {
      if (formats[i].width == 640 && formats[i].height == 480) {
        preferred_format = formats[i];
        // Prefer JPEG or sRGB colorspace if available
        if (formats[i].colorspace == "jpeg" || formats[i].colorspace == "srgb") {
          break;
        }
      }
    }
    
    if (!preferred_format && length(formats) > 0) {
      // Use first available format
      preferred_format = formats[0];
    }
    
    preferred_format.framerate_numerator = 30
    
    if (preferred_format) {
      log.console("Using format:", preferred_format.width + "x" + preferred_format.height,
                  "FPS:", preferred_format.framerate_numerator + "/" + preferred_format.framerate_denominator,
                  "Format:", preferred_format.format,
                  "Colorspace:", preferred_format.colorspace);
      cam_obj = camera.open(cam_id, preferred_format);
    } else {
      cam_obj = camera.open(cam_id);
    }
    
    if (!cam_obj) {
      log.error("Failed to open camera!");
      $stop();
      return;
    }
    
    log.console("Camera driver:", cam_obj.get_driver());
    
    // Get and display the actual format being used
    var actual_format = cam_obj.get_format();
    log.console("Actual camera format:");
    log.console("  Resolution:", actual_format.width + "x" + actual_format.height);
    log.console("  Format:", actual_format.format);
    log.console("  Colorspace:", actual_format.colorspace);
    log.console("  FPS:", actual_format.framerate_numerator + "/" + actual_format.framerate_denominator);
    
    // Start capturing after a short delay to wait for approval
    $delay(start_capturing, 0.5);
  });
});

var captured = false

function start_capturing() {
  if (!cam_approved) {
    log.console("Waiting for camera approval...");
    $delay(start_capturing, 0.1);
    return;
  }
  
  var frame = 0;
  var start_time = os.now();
  
  function capture_and_draw() {
    frame++;
    var t = os.now() - start_time;
    
    // Clear the screen with a dark background
    send(video_actor, {
      kind: "renderer",
      id: renderer_id,
      op: "set",
      prop: "drawColor",
      value: [0.1, 0.1, 0.15, 1]
    });
    
    send(video_actor, {
      kind: "renderer",
      id: renderer_id,
      op: "clear"
    });
    
    // Clear draw2d commands
    draw2d.clear();
    
    // Capture frame from camera
    var surface = cam_obj.capture()

    if (surface) {
      // Create texture from surface directly
      send(video_actor, {
        kind: "renderer",
        id: renderer_id,
        op: "loadTexture",
        data: surface
      }, function(tex_response) {
        if (tex_response.id) {
          // Destroy old texture if exists to avoid memory leak
          if (webcam_texture) {
            send(video_actor, {
              kind: "texture",
              id: webcam_texture,
              op: "destroy"
            });
          }
          webcam_texture = tex_response.id;
        }
      });
    }
    
    // Draw the webcam texture if we have one
    if (webcam_texture) {
      send(video_actor, {
        kind: "renderer",
        id: renderer_id,
        op: "copyTexture",
        data: {
          texture_id: webcam_texture,
          dest: {x: 50, y: 50, width: 640, height: 480}
        }
      });
    } else {
      // Draw placeholder text while waiting for first frame
//      draw2d.text("Waiting for webcam...", {x: 200, y: 250, size: 20});
    }
    
    // Draw info
    /*
    draw2d.text("Camera: " + camera.name(cam_id), {x: 20, y: 20, size: 16});
    draw2d.text("Position: " + camera.position(cam_id), {x: 20, y: 40, size: 16});
    draw2d.text("Frame: " + frame, {x: 20, y: 60, size: 16});
    */
    // Flush all commands to renderer
    draw2d.flush();
    
    // Present the frame
    send(video_actor, {
      kind: "renderer",
      id: renderer_id,
      op: "present"
    });
    
    // Schedule next frame (30 FPS for webcam)
    if (frame < 300) { // Run for 10 seconds
      $delay(capture_and_draw, 1/30);
    } else {
      log.console("Test completed - captured", frame, "frames");
      
      // Clean up resources
      if (webcam_texture) {
        send(video_actor, {
          kind: "texture",
          id: webcam_texture,
          op: "destroy"
        });
      }
      
      // Note: Camera is automatically closed when the object is garbage collected
      cam_obj = null;
      
      $delay($stop, 0.5);
    }
  }
  
  capture_and_draw();
}

$delay(_ => {
  // Capture frame from camera
  var surface = cam_obj.capture().convert("rgba8888", "srgb")
  log.console('capturing!')
  graphics.save_png("test.png", surface.width, surface.height, surface.pixels(),surface.pitch)
}, 3)

// Stop after 12 seconds if not already stopped
$delay($stop, 12);