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

// Lädt eine TIFF-Datei und gibt sie als RGBA-Raster zurück (libtiff-Standard für den Import)
bool loadTIFF(const char* filename, uint32_t& width, uint32_t& height, std::vector<uint32_t>& raster) {
    TIFF* tif = TIFFOpen(filename, "r");
    if (!tif) {
        std::cerr << "Fehler: Konnte " << filename << " nicht oeffnen." << std::endl;
        return false;
    }

    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);

    raster.resize(width * height);

    if (!TIFFReadRGBAImageOriented(tif, width, height, raster.data(), ORIENTATION_TOPLEFT, 0)) {
        std::cerr << "Fehler beim Lesen der Pixeldaten von " << filename << std::endl;
        TIFFClose(tif);
        return false;
    }

    TIFFClose(tif);
    return true;
}

// Schreibt ein reines 24-Bit-RGB-Raster (3 Bytes pro Pixel, ohne Alpha)
bool writeTIFF24Bit(const char* filename, uint32_t width, uint32_t height, const std::vector<uint8_t>& rgbRaster) {
    TIFF* tifOut = TIFFOpen(filename, "w");
    if (!tifOut) {
        std::cerr << "Fehler beim Erstellen der Ausgabedatei: " << filename << std::endl;
        return false;
    }

    TIFFSetField(tifOut, TIFFTAG_IMAGEWIDTH, width);
    TIFFSetField(tifOut, TIFFTAG_IMAGELENGTH, height);
    TIFFSetField(tifOut, TIFFTAG_SAMPLESPERPIXEL, 3);         // Nur R, G, B (24 Bit)
    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);

    // Zeilenweise schreiben. Eine Zeile hat width * 3 Bytes.
    uint32_t scanlineSize = width * 3;
    for (uint32_t row = 0; row < height; row++) {
        void* rowPtr = const_cast<uint8_t*>(&rgbRaster[row * scanlineSize]);
        if (TIFFWriteScanline(tifOut, rowPtr, row, 0) < 0) {
            std::cerr << "Fehler beim Schreiben der Zeile " << row << std::endl;
            TIFFClose(tifOut);
            return false;
        }
    }

    TIFFClose(tifOut);
    return true;
}

int main() {
    const char* fileOben = "oben.tif";
    const char* fileUnten = "unten.tif";

    uint32_t width, height, wUnten, hUnten;
    std::vector<uint32_t> rasterOben;
    std::vector<uint32_t> rasterUnten;

    if (!loadTIFF(fileOben, width, height, rasterOben)) return 1;
    if (!loadTIFF(fileUnten, wUnten, hUnten, rasterUnten)) return 1;

    if (width != wUnten || height != hUnten) {
        std::cerr << "Fehler: Die Dimensionen stimmen nicht ueberein!" << std::endl;
        return 1;
    }

    // Speicher für 24-Bit-RGB-Bilder reservieren (3 Bytes pro Pixel, initialisiert mit 255 = Weiss)
    std::vector<uint8_t> rgbTop(width * height * 3, 255);
    std::vector<uint8_t> rgbBot(width * height * 3, 255);

    std::cout << "Generiere 24-Bit top.tiff und bot.tiff..." << std::endl;

    for (uint32_t y = 0; y < height; y++) {
        for (uint32_t x = 0; x < width; x++) {
            uint32_t idxNormal = y * width + x;
            uint32_t idxMirrored = y * width + ((width - 1) - x);

            // 1. Pixel-Zustände aus dem RGBA-Input bestimmen
            uint32_t pO = rasterOben[idxNormal];
            bool kupferOben = ((pO & 0xFF) == 0 && ((pO >> 8) & 0xFF) == 0 && ((pO >> 16) & 0xFF) == 0);

            uint32_t pU = rasterUnten[idxMirrored];
            bool kupferUnten = ((pU & 0xFF) == 0 && ((pU >> 8) & 0xFF) == 0 && ((pU >> 16) & 0xFF) == 0);

            // 2. Indizes für das dreifach breite RGB-Ausgabe-Array berechnen
            uint32_t rgbIdxNormal = idxNormal * 3;
            uint32_t rgbIdxMirrored = idxMirrored * 3;

            // --- TOP-Ansicht (Blick von oben, ungespiegelt) ---
            if (kupferOben && kupferUnten) {
                // Überlappung = Schwarz
                rgbTop[rgbIdxNormal + 0] = 0; // R
                rgbTop[rgbIdxNormal + 1] = 0; // G
                rgbTop[rgbIdxNormal + 2] = 0; // B
            } else if (kupferOben) {
                // Nur oben = GRAU
                rgbTop[rgbIdxNormal + 0] = 50;
                rgbTop[rgbIdxNormal + 1] = 50;
                rgbTop[rgbIdxNormal + 2] = 50;
            } else if (kupferUnten) {
                // Nur unten = BLAU
                rgbTop[rgbIdxNormal + 0] = 0;
                rgbTop[rgbIdxNormal + 1] = 255;
                rgbTop[rgbIdxNormal + 2] = 0;
            }
        }
    }

    for (uint32_t y = 0; y < height; y++) {
        for (uint32_t x = 0; x < width; x++) {
            uint32_t idxNormal = y * width + x;
            uint32_t idxMirrored = y * width + ((width - 1) - x);

            uint32_t pU = rasterUnten[idxNormal];
            bool kupferUnten = ((pU & 0xFF) == 0 && ((pU >> 8) & 0xFF) == 0 && ((pU >> 16) & 0xFF) == 0);

            uint32_t pO = rasterOben[idxMirrored];
            bool kupferOben = ((pO & 0xFF) == 0 && ((pO >> 8) & 0xFF) == 0 && ((pO >> 16) & 0xFF) == 0);

            uint32_t rgbIdxNormal = idxNormal * 3;
            uint32_t rgbIdxMirrored = idxMirrored * 3;

            // --- BOT-Ansicht (Blick von unten) ---

            if (kupferOben) {
                // (0,255,0)= GRUEN
                rgbBot[rgbIdxNormal + 0] = 0;   // R
                rgbBot[rgbIdxNormal + 1] = 255; // G
                rgbBot[rgbIdxNormal + 2] = 0;   // B
            }

            if (kupferUnten) {
                // (50,50,50) = GRAU
                rgbBot[rgbIdxNormal + 0] = 50; // R
                rgbBot[rgbIdxNormal + 1] = 50; // G
                rgbBot[rgbIdxNormal + 2] = 50; // B
            }
            
            if (kupferOben && kupferUnten) {
                // (0,0,0) = SCHWARZ
                rgbBot[rgbIdxNormal + 0] = 0; // R
                rgbBot[rgbIdxNormal + 1] = 0; // G
                rgbBot[rgbIdxNormal + 2] = 0; // B
            }
        }
    }

    // 3. Ausgabe schreiben (Reines RGB, platzsparend)
    std::cout << "Schreibe top.tiff..." << std::endl;
    if (!writeTIFF24Bit("all_top.tiff", width, height, rgbTop)) return 1;

    std::cout << "Schreibe bot.tiff..." << std::endl;
    if (!writeTIFF24Bit("all_bot.tiff", width, height, rgbBot)) return 1;

    std::cout << "Fertig! Beide Dateien im platzsparenden 24-Bit-RGB-Format erstellt." << std::endl;
    return 0;
}
