import java.awt.Point;
import java.io.File;
import java.io.IOException;


/**
 * Test der Klasse 'RadolanReader'
 * ===============================
 * 
 * Zweck
 * -----
 * 1) Kontrolle des RadolanReaders nach Updates mittels Testmethoden und Testdateien.
 * 2) Demo wie die Methoden des RadolanReaders verwendet werden
 * 
 * Bekannte Nutzer
 * ---------------
 * LfU Augsburg
 * 
 * Anwendung
 * ---------
 * Gewünschten Test (= Produkt) in main() aktivieren und
 * diese Klasse starten.
 * Die entsprechenden Testdaten müssen vorliegen.
 * 
 * @author
 * -------
 * Deutscher Wetterdienst - Hydrometeorologie - Mario Hafer, KU42a
 * Version: s. die Zuweisung im Programmcode des 'RadolanReaders' => VERSION
 * 
 * Anpassungen (Historie mit Klasse 'RadolanReader' abgleichen)
 * -----------
 * 2019-03-07: Lesen des RADVOR-RE-Formats eingebaut (Anfrage LfU)
 *             da größere Umbauarbeiten an den Methoden und Attributen -
 *             mit Wegfall der Klasse 'Pixel' großer Versionssprung
 *             -> Version 2.0
 * 2017-03-28: RW-Tests und RQ-Kompatibiltätstest (LfU möchte damit auch RADVOR-RQ verarbeiten)
 *             -> Version 1.0
 */
public class RadolanReaderTest {
    
    final int MISSING = -1;



    /*
     * -------------------- Nur Ausgabemethoden ----------------------
     */

    private void out(String msg) {
	out(msg, true);
    }
    private void out(String msg, boolean ok) {
	String printout = getClass().getName() + ": " + msg;
	if(ok)
	    System.out.println(printout);
	else
	    System.err.println(printout);
    }




    /*
     * Testmethoden
     */


    /** Führt zwei Tests am RW aus 
     * @throws IOException */
    public void test_RADOLAN_RW() throws IOException {

        File rw_file = new File("testdaten/Feldberg-Speiche_und_Bodenflag", "raa01-rw_10000-1609121650-dwd---bin");

        if(! rw_file.exists()) {
            out("File '" + rw_file + "' wurde nicht gefunden!", false);
            return;
        }


        System.out.println("### TEST RADOLAN   RW Niederschlag ###\n");


        // Init. RadolanReader:
        RadolanReader rr = new RadolanReader(rw_file);    // file open


        int minimum_threshold = -10;    // damit sicher alle Werte ausgegeben (auch Fehl) werden


        // x, y
        Point cp = new Point(270, 69);

        // Distance (oben, unten, links, rechts)
        int[] d = new int[] { 50, 50, 50, 50 };

        /*
         * Integer:
         */
        int[][] int_field = rr.readArea(cp, d);    // Datei wird geschlossen

        print_field_values_with_minimum_of(int_field, minimum_threshold);

        /*
         * Float:
         */
        //System.out.println();
        //print_field_values_with_minimum_of(rr.float_field(), -10);    // alles ausgeben


        System.out.println("\n");



        System.out.println("### TEST RADOLAN   RW Bodenflag ###\n");
        /*
         * hier: Feldberg-Speiche
         */

        // x, y
        cp = new Point(376, 69);

        // Distance (oben, unten, links, rechts)
        d = new int[] { 10, 10, 20, 20 };


        // neu lesen

        // Init. RadolanReader:
        rr = new RadolanReader(rw_file);    // file open

        int_field = rr.readArea(cp, d);

        print_field_values_with_minimum_of(int_field, minimum_threshold);
    }




    /** Test mit einem RQ-Produkt.
     * Die Methode mit Ausgabeformatierung wird in diesem Test für
     * das empfangene Feld nicht verwendet (es wäre zu groß), sondern
     * die Werte werden einfach direkt ausgegeben.
     * @throws IOException 
     */
    public void test_RADVOR_RQ() throws IOException {

	System.out.println("### TEST RADVOR   RQ ###\n");


	File rq_file = new File("testdaten/RQ", "RQ1703210645_000");

	if(! rq_file.exists()) {
	    out("File '" + rq_file + "' wurde nicht gefunden!", false);
	    return;
	}


	// Init. RadolanReader:
	RadolanReader rr = new RadolanReader(rq_file);    // file open

	// Reader konfigurieren:
	//rr.raw_values(true);    // Werte als Roh-Werte nehmen

	// Feld lesen:
	//int[][] int_field = rr.readAll();
	rr.readAll();

	/*
	 * Integer
	 */

	/* Zum Testen: bestimmte, häufig vorkommende Werte ausschließen (blacklisten),
	 * indem diese auf negativen Wert (= Missing) gesetzt werden: */
	//set_all_values_to_missing_below(int_field, 0);    // keine negativen Werte
	//set_all_values_to_missing_below(int_field, 1);    // keine Nuller und weniger

	//int i_threshold = 0;    // alles unter 0 nicht ausgeben
	//print_field_values_with_minimum_of(int_field, i_threshold);

	/*
	 * Float
	 */

	float f_threshold = 1;    // alles AB diesem Wert
	print_field_values_with_minimum_of(rr.float_field(), f_threshold);


    } // RQ



    /** Test mit einem RV-Produkt.
     * Die Methode mit Ausgabeformatierung wird in diesem Test für
     * das empfangene Feld nicht verwendet (es wäre zu groß), sondern
     * die Werte werden einfach direkt ausgegeben.
     * @throws IOException 
     */
    public void test_RADVOR_RV() throws IOException {

	System.out.println("### TEST RADVOR   RV ###\n");


	File rv_file = new File("testdaten/RV", "RV1709290745_000_MF002");

	if(! rv_file.exists()) {
	    out("File '" + rv_file + "' wurde nicht gefunden!", false);
	    return;
	}


	// Init. RadolanReader:
	RadolanReader rr = new RadolanReader(rv_file);    // file open

	// Reader konfigurieren:
	//rr.raw_values(true);    // Werte als Roh-Werte nehmen

	// Feld lesen:
	int[][] int_field = rr.readAll();

    
	//int threshold = -10;	// alles ausgeben, auch Fehl
	//int threshold = 0;
	int threshold = 1;

	print_field_values_with_minimum_of(int_field, threshold);    // alles AB diesem Wert


    } // RV




    /** Test mit einem RE-Produkt.
     * Die Methode mit Ausgabeformatierung wird in diesem Test für
     * das empfangene Feld nicht verwendet (es wäre zu groß), sondern
     * die Werte werden einfach direkt ausgegeben.
     * @throws IOException 
     */
    public void test_RADVOR_RE() throws IOException {

	System.out.println("### TEST RADVOR   RE ###\n");


	File re_file = new File("testdaten/RE", "RE1903040700_000");

	if(! re_file.exists()) {
	    out("File '" + re_file + "' wurde nicht gefunden!", false);
	    return;
	}


	// Init. RadolanReader:
	RadolanReader rr = new RadolanReader(re_file);    // file open

	// Reader konfigurieren:
	//rr.raw_values(true);    // Werte als Roh-Werte nehmen

	// Feld lesen:
	int[][] int_field = rr.readAll();


	/*
	 * Integer
	 */

	/* Zum Testen: bestimmte, häufig vorkommende Werte ausschließen (blacklisten),
	 * indem diese auf negativen Wert (= Missing) gesetzt werden: */
	//set_all_values_to_missing_below(int_field, 0);    // keine negativen Werte
	//set_all_values_to_missing_below(int_field, 1);    // keine Nuller und weniger
	//set_all_values_to_missing_equal_to(int_field, 10692);    // zusammen mit rr.raw_values(true)
	set_all_values_to_missing_equal_to(int_field, 0);    // im RE fast alles Nuller

	//print_field_values_with_minimum_of(int_field, 0);    // alles AB diesem Wert

	/*
	 * Float
	 */

	float f_threshold = 0.1F;    // alles AB diesem Wert. Missings raus und keine Nuller
	print_field_values_with_minimum_of( rr.float_field(), f_threshold);


    } // RE


    /** Alle Werte im Int-Feld bis zu einem bestimmten Schwellenwert blacklisten (set to missing). */
    private void set_all_values_to_missing_below(int[][] int_field, int threshold) {

	out( String.format("set_all_values_to_missing_below(%d) ...", threshold) );


	int rows = int_field.length;
	int cols = int_field[0].length;


	// Die Reihenfolge des Durchlaufs ist hier egal, da
	// die Werte nur manipuliert zurückgespeichert werden.

	for(int y=0; y < rows; y++) {

	    // Spalten (einer Zeile) von W nach E
	    for(int x=0; x < cols; x++) {

		// Nur dann ist etwas zu tun:
		if(int_field[y][x] < threshold)
		    int_field[y][x] = MISSING;
	    } // cols

	} // rows
    }

    /** Alle Werte im Int-Feld bis zu einem bestimmten Schwellenwert blacklisten (set to missing). */
    private void set_all_values_to_missing_equal_to(int[][] int_field, int value) {

	out( String.format("set_all_values_to_missing_equal_to(%d) ...", value) );


	int rows = int_field.length;
	int cols = int_field[0].length;


	// Die Reihenfolge des Durchlaufs ist hier egal, da
	// die Werte nur manipuliert zurückgespeichert werden.

	for(int y=0; y < rows; y++) {

	    // Spalten (einer Zeile) von W nach E
	    for(int x=0; x < cols; x++) {

		// Nur dann ist etwas zu tun:
		if(int_field[y][x] == value)
		    int_field[y][x] = MISSING;
	    } // cols

	} // rows
    }


    /** Gibt das 2D-Array so aus, wie es im Speicher steht.
     * Integer-Field-Version */
    private void print_field_values_with_minimum_of(int[][] int_field,  int threshold) {

	// Info bringt Sicherheit bezüglich der Orientierung des Rasters (Norden oben?):
	//rr.print_orientation_info();


	for(int y=0; y < int_field.length; y++) {

	    /* Die X-Werte sind von der Drehung des Feldes unberührt
	     * Spalten (einer Zeile) von W nach E (x nimmt zu) */
	    for(int x=0; x < int_field[y].length; x++) {

		int value = int_field[y][x];

		// nicht ausgeben:
		if(value < threshold)
		    continue;

		// Wert gültig

		System.out.print(value + " ");

	    } // x

	    System.out.println(); // Am Ende jeder Zeile (x) Zeilenwechsel

	} // y

    } // print_field_values_with_minimum_of()


    /** Gibt das 2D-Array so aus, wie es im Speicher steht.
     * Float-Field-Version */
    private void print_field_values_with_minimum_of(float[][] float_field,  float threshold) {

	// Info bringt Sicherheit bezüglich der Orientierung des Rasters (Norden oben?):
	//rr.print_orientation_info();


	for(int y=0; y < float_field.length; y++) {

	    /* Die X-Werte sind von der Drehung des Feldes unberührt
	     * Spalten (einer Zeile) von W nach E (x nimmt zu) */
	    for(int x=0; x < float_field[y].length; x++) {

		float value = float_field[y][x];

		// nicht ausgeben:
		if(value < threshold)
		    continue;

		// Wert gültig

		System.out.print(value + " ");

	    } // x

	    System.out.println(); // Am Ende jeder Zeile (x) Zeilenwechsel

	} // y

    } // print_field_values_with_minimum_of()




    /*
     * 
     * ##################################################################################
     * 
     */


    public static void main(String[] args) throws IOException {

	// Prints the complete absolute path from where your application was initialized:
	System.out.printf("Working Directory = %s %n%n", System.getProperty("user.dir"));



	RadolanReaderTest rrt = new RadolanReaderTest();


	String test;

	// gewünschtes Produkt aktivieren:
	test = "RW";
	//test = "RQ";
	//test = "RV";
	//test = "RE";



	/* 
	 * RADOLAN-RW-Test
	 * 
	 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
	if(test.equalsIgnoreCase("RW")) {
	    rrt.test_RADOLAN_RW();
	    System.exit(0);
	}
	// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<



	/*
	 * RADVOR-Tests
	 */

	/* RQ-Test
	 * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
	if(test.equalsIgnoreCase("RQ")) {
	    rrt.test_RADVOR_RQ();
	    System.exit(0);
	}
	// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


	/* RV-Test
	 * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
	if(test.equalsIgnoreCase("RV")) {
	    rrt.test_RADVOR_RV();
	    System.exit(0);
	}
	// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


	/* RE-Test
	 * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
	if(test.equalsIgnoreCase("RE")) {
	    rrt.test_RADVOR_RE();
	    System.exit(0);
	}
	// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    } // main


}
