/**
 *  Copyright © 2025, Luis Andrés Lange <https://javacomm.net>
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 *  ----------------------------------------------------------------------------
 *
 *  Exhibit B - "Incompatible With Secondary Licenses" Notice
 *
 *  This Source Code Form is "Incompatible With Secondary Licenses",
 *  as defined by the Mozilla Public License, v. 2.0.
 *
 *  In short:
 *  - This file may be used, modified, and distributed under MPL 2.0 only.
 *  - It may NOT be relicensed under GPL, LGPL, AGPL, or any other Secondary License.
 *
 *  Rationale:
 *  - Ensures that the code remains MPL-2.0.
 *  - Avoids legal conflicts with GPL-licensed libraries (e.g., VideoLAN).
 *  - Maximizes usability for commercial and security-critical applications.
 *
 */
package net.javacomm.client.screencaster;

import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;
import javax.imageio.ImageIO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.javacomm.client.screencaster.FrameBuffer.FrameData;



/**
 * Producer: Erstellt Screenshots im Virtual Thread und schiebt sie in den
 * Buffer.
 */
class CreatePicture implements Runnable {

  private final static Logger log = LogManager.getLogger(CreatePicture.class);
  private static final Robot robot;

  static {
    try {
      robot = new Robot();
    }
    catch (AWTException e) {
      throw new RuntimeException("Robot konnte nicht erzeugt werden", e);
    }
  }

  private final FrameBuffer buffer;
  private final AtomicLong lastTakenProductionTimestamp;
  private final Rectangle screenSize;
  private long counter = 0;

  // Taktung: 40ms entsprechen ca. 10 Bildern pro Sekunde (FPS)
  private final long targetFrameTimeMs = 100;

  CreatePicture(FrameBuffer buffer, AtomicLong timestamp) {
    this.buffer = buffer;
    lastTakenProductionTimestamp = timestamp;
    screenSize = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
  }



  public Rectangle getScreenSize() {
    return screenSize;
  }



  @Override
  public void run() {
    try {
      while (!Thread.currentThread().isInterrupted()) {
        long t0 = System.currentTimeMillis();
        long frameStartNanos = System.nanoTime();

        // 1. Snapshot direkt im Virtual Thread schießen (EDT bleibt völlig frei!)
        BufferedImage image = robot.createScreenCapture(screenSize);

        // 2. Zu PNG komprimieren (reine CPU-Arbeit im Virtual Thread)
        byte[] pngBytes = toPng(image);

        // 3. Frame in den Buffer legen
        buffer.setFrame(new FrameData(pngBytes, ++counter, frameStartNanos));

        // 4. Sanfte Bremse, damit die Schleife nicht Amok läuft
        long elapsed = System.currentTimeMillis() - t0;
        long sleep = targetFrameTimeMs - elapsed;

        if (sleep > 0) {
          Thread.sleep(sleep); // Schläft hocheffizient im Virtual Thread
        }
      }
    }
    catch (InterruptedException e) {
      log.info("Producer sauber beendet");
    }
    catch (IOException e) {
      log.error("Fehler beim Erstellen/Komprimieren des Screenshots", e);
    }
  }



  private byte[] toPng(BufferedImage image) throws IOException {
    try(ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
      ImageIO.write(image, "png", outputStream);
      return outputStream.toByteArray();
    }
  }

}