import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
// Der folgende statische Import von Funktionen ist ganz schlechter Stil
// und wurde nur durchgeführt, um die betreffenden Zeilen zu kürzen. Damit
// ein Screenshot des Codes auch für Sehbeeinträchtigte Menschen lesbar bleibt.
import static java.util.Collections.max;
import static java.util.Collections.min;
import java.util.Comparator;
import java.awt.Color;



public class Median_Cut_SuS {

    public static void main(String[] args){

        /*
        * Hier müssen die gewünschten Änderungen vorgenommen werden, wenn:
        * 1. Anzahl der Farben geändert werden soll (Iterationen sind nicht gleich Anzahl Farben!)
        * 2. Ein anderes Bild bearbeitet werden soll
        * 3. Ein anderer Outputpfad-/name gewählt werden soll
        * 
        * Der Pfad zu den Bildern ist hier relativ zum Working Directory, welches immer der Ordner ist aus 
        * dem heraus die Anwendung gestartet wird. Hier könnten auch Absolute Pfade angegeben werden!
        */
        String RGB_ImageInputPath = "images/59723540_401.jpg";
        String RGB_ImageOutputPath = "images/result.png";
        int iterationSteps = 4;

        
        // BufferedImage ist eine durch Java bereitgestellte Klasse,
        // die den Zugriff auf verschiedene Bildformate, ihre Pixel und deren Farbwerte ermöglicht.
        // Hier werden die Datenstrukturen RGB und alteredRGB initialisiert.
        BufferedImage RGB;
        BufferedImage alteredRGB;

        // Das gewünschte Bild einlesen
        try {
	        RGB = ImageIO.read(new File(RGB_ImageInputPath));
	    } catch (IOException e) {
	    	System.err.println("Image not found. Check the ImagePath!");
            return;
	    }

        // Eine 1-dimensionale Liste der Bildpixel erzeugen.
        // Die Liste hält tatsächlich int[5] Werte für R,G,B,Width und Height jedes Pixels.
        ArrayList<int[]> flattenedImgArray = new ArrayList<int[]>();
        for(int i = 0; i < RGB.getHeight(); i++){
            for(int j = 0; j < RGB.getWidth(); j++){
                int[] list = {new Color(RGB.getRGB(j, i)).getRed(), new Color(RGB.getRGB(j, i)).getGreen(), new Color(RGB.getRGB(j, i)).getBlue(), j, i};
                flattenedImgArray.add(list);
            }
        }


        ArrayList<int[]> returnedFlattenedImgArray = MedianCutAlgorithm(flattenedImgArray,iterationSteps);

        // Diese For-Schleife nimmt jeden einzelnen Pixelwert des RückgabeArrays und speichert ihn an seiner korrekten Position wieder in das Bild.
        // Dafür muss aus den 3 Integern für R,G und B einen einzelnen Integer gemacht werden für ARGB.
        // Das wird hier in dem hinteren Teil durch eine eigentlich sehr simplen Bit-Shift bewerkstelligt.
        // Wir speichern A,R,G und B in einem einzelnen 32-Bit Integer. (A = Transparenz erhält den Wert 255, sprich "Keine Transparenz")
        for(int[] pixelValues : returnedFlattenedImgArray){
            RGB.setRGB(pixelValues[3], pixelValues[4], (255 << 24) | pixelValues[0] << 16 | pixelValues[1] << 8 | pixelValues[2]);
        }

        // Das fertige Bild speichern
        alteredRGB = RGB;
        try {
            ImageIO.write(alteredRGB ,"png", new File(RGB_ImageOutputPath));
        } catch (IOException e){
            System.err.println("Image couldn´t be saved");
        }
    }



    // Rekursiver Codeblock
    public static ArrayList<int[]> MedianCutAlgorithm(ArrayList<int[]> inputListe, int iterationSteps){

        ArrayList<int[]> outputListe = inputListe;

        ArrayList<Integer> rK = new ArrayList<Integer>(inputListe.size()); // rK = roter Kanal
        ArrayList<Integer> gK = new ArrayList<Integer>(inputListe.size()); // gK = grüner Kanal
        ArrayList<Integer> bK = new ArrayList<Integer>(inputListe.size()); // bK = blauer Kanal

        int sumOfRed = 0; int sumOfGreen = 0; int sumOFBlue = 0;


        for (int[] item : inputListe) {
        // Aufgabe 3 b) gehört hierhin
        }



        // Aufgabe 3 e) gehört hierhin



        
        // Den selbst geschrieben Comparator erzeugen und die flattenedImgArray ArrayList
        // damit sortieren. Mit .set(1) wird die Liste nach ihrem zweiten Parameter sortiert.
        // Das wäre "Grün" im R,G,B,Width,Height
        customComparator customComp = new customComparator();

        if(max(rK) - min(rK) > max(gK) - min(gK)
        && max(rK) - min(rK) > max(bK) - min(bK))
                customComp.set(0);
        else if(max(gK) - min(gK) > max(rK) - min(rK)
             && max(gK) - min(gK) > max(bK) - min(bK))
                customComp.set(1);
        else if(max(bK) - min(bK) > max(gK) - min(gK)
             && max(bK) - min(bK) > max(rK) - min(rK))
                customComp.set(2);
            
        Collections.sort(inputListe, customComp);



        // Aufgabe 3 c)
        ArrayList<int[]> tempArray1 = 
        ArrayList<int[]> tempArray2 = 



        // Aufgabe 3 d)
        



        return outputListe;
    }






    // Um die Int[5]´s vergleichen zu können, ist eine Funktion nötig, die diese Int[5]´s auch vergleichen kann.
    // Dazu braucht es einen "Comparator"
    static class customComparator implements Comparator<int[]>{
        int RGorB = 0;

        public void set(int whichRGBisHighest){
            if(whichRGBisHighest < 0 || 2 < whichRGBisHighest){
                System.out.println("Es können nur R,G oder B zum sortieren ausgewählt werden.");
                return;
            }
            RGorB = whichRGBisHighest;
        }

        public int compare(int[] firstIntArray, int[] secondIntArray){
            return Integer.compare(firstIntArray[RGorB], secondIntArray[RGorB]);
        }
    }
}
