#include <iostream>
#include <vector>
#include <tiffio.h>

// Funktion, um einen einzelnen Pixel im RGBA-Array sicher rot zu färben
void setPixelRed(std::vector<uint32_t>& raster, int width, int height, int x, int y) {
    // Sicherstellen, dass wir nicht außerhalb des Bildes zeichnen
    if (x >= 0 && x < width && y >= 0 && y < height) {
        // TIFF-RGBA-Format: 0xFF0000FF ist oft Rot (abhängig von Endianness: ABGR oder RGBA)
        // Bei libtiff unter Linux x86_64 ist es meistens: AAAAAAAA BBBBBBBB GGGGGGGG RRRRRRRR
        // Also: Alpha (0xFF), Blau (0x00), Grün (0x00), Rot (0xFF) -> 0xFF0000FF
        raster[y * width + x] = 0xFF0000FF; 
    }
}

// Midpoint-Kreisalgorithmus nach Bresenham
void drawCirclePure(std::vector<uint32_t>& raster, int width, int height, int xc, int yc, int r) {
    int x = 0;
    int y = r;
    int d = 3 - 2 * r;

    while (y >= x) {
        // Alle 8 Oktanten des Kreises symmetrisch zeichnen
        setPixelRed(raster, width, height, xc + x, yc + y);
        setPixelRed(raster, width, height, xc - x, yc + y);
        setPixelRed(raster, width, height, xc + x, yc - y);
        setPixelRed(raster, width, height, xc - x, yc - y);
        setPixelRed(raster, width, height, xc + y, yc + x);
        setPixelRed(raster, width, height, xc - y, yc + x);
        setPixelRed(raster, width, height, xc + y, yc - x);
        setPixelRed(raster, width, height, xc - y, yc - x);

        x++;

        if (d > 0) {
            y--;
            d = d + 4 * (x - y) + 10;
        } else {
            d = d + 4 * x + 6;
        }
    }
}

int main() {
    const char* inputFile = "eingabe.tif";
    const char* outputFile = "ausgabe.tif";

    // 1. Eingabe-TIFF öffnen
    TIFF* tifIn = TIFFOpen(inputFile, "r");
    if (!tifIn) {
        std::cerr << "Fehler beim Öffnen der Eingabedatei!" << std::endl;
        return 1;
    }

    uint32_t width, height;
    TIFFGetField(tifIn, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField(tifIn, TIFFTAG_IMAGELENGTH, &height);

    // Speicher für RGBA-Pixel reservieren
    std::vector<uint32_t> raster(width * height);

    // Bild standardisiert einlesen (ORIENTATION_TOPLEFT sorgt für normales Koordinatensystem)
    if (!TIFFReadRGBAImageOriented(tifIn, width, height, raster.data(), ORIENTATION_TOPLEFT, 0)) {
        std::cerr << "Fehler beim Lesen der Pixeldaten!" << std::endl;
        TIFFClose(tifIn);
        return 1;
    }
    TIFFClose(tifIn);

    std::cout << "Bild erfolgreich geladen (" << width << "x" << height << ")." << std::endl;

    // 2. Kreis in das RAM-Raster einzeichnen
    int centerX = width / 2;
    int centerY = height / 2;
    int radius = 100; // Radius in Pixeln
    drawCirclePure(raster, width, height, centerX, centerY, radius);

    // 3. Ausgabe-TIFF erstellen und konfigurieren
    TIFF* tifOut = TIFFOpen(outputFile, "w");
    if (!tifOut) {
        std::cerr << "Fehler beim Erstellen der Ausgabedatei!" << std::endl;
        return 1;
    }

    // Essentielle TIFF-Tags für ein unkomprimiertes RGBA-Bild setzen
    TIFFSetField(tifOut, TIFFTAG_IMAGEWIDTH, width);
    TIFFSetField(tifOut, TIFFTAG_IMAGELENGTH, height);
    TIFFSetField(tifOut, TIFFTAG_SAMPLESPERPIXEL, 4);         // R, G, B, A
    TIFFSetField(tifOut, TIFFTAG_BITSPERSAMPLE, 8);          // 8 Bit pro Kanal
    TIFFSetField(tifOut, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
    TIFFSetField(tifOut, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField(tifOut, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);

    // Dem TIFF-Reader mitteilen, dass das 4. Sample Alpha ist
    uint16_t extraSamples[] = { EXTRASAMPLE_ASSOCALPHA };
    TIFFSetField(tifOut, TIFFTAG_EXTRASAMPLES, 1, extraSamples);

    // 4. Daten Zeile für Zeile schreiben
    for (uint32_t row = 0; row < height; row++) {
        // Zeiger auf den Anfang der aktuellen Zeile im Vektor setzen
        void* rowPtr = &raster[row * width];
        if (TIFFWriteScanline(tifOut, rowPtr, row, 0) < 0) {
            std::cerr << "Fehler beim Schreiben der Zeile " << row << std::endl;
            TIFFClose(tifOut);
            return 1;
        }
    }

    TIFFClose(tifOut);
    std::cout << "Datei erfolgreich als '" << outputFile << "' gespeichert." << std::endl;

    return 0;
}
