import java.sql.*;
import java.util.LinkedList;
import java.util.Map;
import java.util.HashMap;

/**
 * Die Klasse Connect stellt Methoden zur Verfügung, um mit einer SQLite-Datenbank zu interagieren.
 * Sie unterstützt das Öffnen und Schließen von Verbindungen sowie das Abfragen von Daten,
 * um Objekte für weitere Verarbeitungen zu erstellen.
 * 
 * @author Benedikt Lindemann
 */
public class Connect {
   
    /**
     * Stellt eine Verbindung zur angegebenen SQLite-Datenbank her.
     * @param dbFileName Der Dateiname der SQLite-Datenbank.
     * @return Eine Connection-Instanz, die zur Interaktion mit der Datenbank verwendet wird.
     */
    public static Connection connect(String dbFileName) {
        Connection conn = null;
        try {
            // db parameters
            String url = "jdbc:sqlite:"+dbFileName;//"jdbc:sqlite:C:/Users/bened/bycsdrive - Benedikt Lindemann@0323.drive.bycs.de/Persönlich/teacherOfTheYear/FischDB_Entscheidungsbaum/FischDB.db";
            // create a connection to the database
            conn = DriverManager.getConnection(url);

        } catch (SQLException e) {
            System.out.println(e.getMessage());
        } 
        return conn;
    }

    /**
     * Schließt die gegebene Datenbankverbindung.
     * @param conn Die zu schließende Connection-Instanz.
     */
    public static void closeConnection(Connection conn) {
        try {
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException ex) {
            System.out.println(ex.getMessage());
        }
    }

    // /**
     // * Erstellt eine Liste von Fisch-Objekten aus der Datenbank.
     // * @return Eine LinkedList von FISCH-Objekten, die aus der Datenbank geladen wurden.
     // */
    // public static LinkedList<FISCH> fischeListe() {
        // LinkedList<FISCH> fische = new LinkedList<FISCH>();
        // Connection conn = connect("FischDB.db");
        // try {
            // Statement stmt = conn.createStatement();
            // ResultSet rs = stmt.executeQuery( "SELECT * FROM FISCHDB;" );

            // while ( rs.next() ) {
                // String muster = rs.getString("muster");
                // String bauchfarbe = rs.getString("bauchfarbe");
                // String augenfarbe = rs.getString("augenfarbe");
                // String schuppenfarbe = rs.getString("schuppenfarbe");
                // String flossenfarbe = rs.getString("flossenfarbe");
                // String groesse = rs.getString("groesse");
                // String angelfarbe = rs.getString("angelfarbe");
                // String zaehne = rs.getString("zaehne");
                // String label = rs.getString("label");
                // boolean istFriedlich = label.equals("friedlich");
                
                // fische.add(new FISCH(muster,bauchfarbe,augenfarbe,schuppenfarbe,flossenfarbe, groesse, angelfarbe, zaehne, istFriedlich));
            // }
            // rs.close();
            // stmt.close();
        // } catch (SQLException e) {
            // System.out.println(e.getMessage());
        // }
        // closeConnection(conn);
        // return fische;
    // }

    /**
     * Lädt Daten aus einer angegebenen Tabelle der Datenbank und gibt sie als Liste von GELABELTEDATEN-Objekten zurück.
     * @param db Der Datenbankname.
     * @param table Der Tabellenname in der Datenbank.
     * @param columns Die Spaltennamen, die geladen werden sollen.
     * @param labelColName Der Name der Spalte, die das Label enthält.
     * @param limit Maximale Anzahl von Zeilen, die geladen werden sollen.
     * @param offset Die Anzahl der Zeilen, die übersprungen werden sollen.
     * @return Eine Liste von GELABELTEDATEN-Objekten.
     */
    public static LinkedList<GELABELTEDATEN> getDatenAusDB(String db, String table, String[] columns, String labelColName, int limit, int offset) {
        LinkedList<GELABELTEDATEN> data = new LinkedList<GELABELTEDATEN>();
        Connection conn = connect(db);
        try {
            Statement stmt = conn.createStatement();
            //ResultSet rs = stmt.executeQuery( "SELECT * FROM FISCHDB;" );
            ResultSet rs;
            if (limit ==0) {
                rs = stmt.executeQuery( "SELECT * FROM "+table+";" );
            } else {
                rs = stmt.executeQuery( "SELECT * FROM "+table+" LIMIT "+limit+" OFFSET "+offset+";" );
            }

            while ( rs.next() ) {
                Map<String, String> features = new HashMap<String, String>();
                
                for (String col : columns) {
                  
                    features.put(col, rs.getString(col));
                
                }
                data.add(new GELABELTEDATEN(features, rs.getString(labelColName)));

            }
            rs.close();
            stmt.close();
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        closeConnection(conn);
        return data;
    }
    
    /**
     * Erzeugt die gelabelten Daten-Liste aus dem grossen Datensatz der Fische. Die Parameter dienen
     * der Aufteilung in Trainings- und Testdaten.
     *
     * @param limit Maximale Anzahl von Zeilen, die geladen werden sollen.
     * @param offset Die Anzahl der Zeilen, die übersprungen werden sollen.
     * @return Eine Liste von GELABELTEDATEN-Objekten.
     */
    public static LinkedList<GELABELTEDATEN> getIrisDatensatz(int limit, int offset) {
        return getDatenAusDB("iris.db", "IrisDatensatz", new String[]{"kelchlaenge", "kelchbreite", "bluetenlaenge", "bluetenbreite"}, "label", limit, offset);
    }
    
    // /**
     // * Erzeugt die gelabelten Daten-Liste aus dem grossen Datensatz der Fische. Die Parameter dienen
     // * der Aufteilung in Trainings- und Testdaten.
     // *
     // * @param limit Maximale Anzahl von Zeilen, die geladen werden sollen.
     // * @param offset Die Anzahl der Zeilen, die übersprungen werden sollen.
     // * @return Eine Liste von GELABELTEDATEN-Objekten.
     // */
    // public static LinkedList<GELABELTEDATEN> getFischeGrosserDatensatz(int limit, int offset) {
        // return getDatenAusDB("FischDB.db", "FischeGrosserDatensatz", new String[]{"muster", "bauchfarbe", "augenfarbe", "schuppenfarbe", "flossenfarbe", "groesse", "angelfarbe","zaehne"}, "label", limit, offset);
    // }
    
    // /**
     // * Erzeugt die gelabelten Daten-Liste aus dem kleinen Datensatz der Fische. Die Parameter dienen
     // * der Aufteilung in Trainings- und Testdaten.
     // *
     // * @param limit Maximale Anzahl von Zeilen, die geladen werden sollen.
     // * @param offset Die Anzahl der Zeilen, die übersprungen werden sollen.
     // * @return Eine Liste von GELABELTEDATEN-Objekten.
     // */
    // public static LinkedList<GELABELTEDATEN> getFischeKleinerDatensatz(int limit, int offset) {
        // return getDatenAusDB("FischDB.db", "FischeKleinerDatensatz", new String[]{"muster", "bauchfarbe", "schuppenfarbe", "flossenfarbe"}, "label", limit, offset);
    // }
}