package kuchenBasar;

import java.sql.*;
import java.util.ArrayList;

import javax.swing.JOptionPane;

import util.*;

/**
 * Datenbankzugriffsmodul Kuchen
 * 
 * @author Bernd Schubert
 * 
 */
public class KuchenDB
{
  private KuchenDB()
  {
  }

  /**
   * 
   * @return Ist die Kuchen-Tabelle erreichbar
   * 
   * Zweck dieser Abfrage ist nur die Exception, die das MainFrame auswerten kann
   */
  public static boolean getOK() throws Exception
  {
    String sql = " SELECT COUNT(*) ";
          sql += " FROM kuchen ";

    Object obj = DBConnection.executeScalarCheck( sql );

    if ( obj != null )
        return true;

    return false;
  }

  /**
   * 
   * @return Aktuelle ID (z.B. gerade beim Insert erzeugt)
   */
  private static int getMaxID()
  {
    String sql = " SELECT MAX(ID) ";
          sql += " FROM kuchen ";

    int retValue = -1;

    try
    {
      Object obj = DBConnection.executeScalar( sql );

      if ( obj != null )
        retValue = (int)obj;
    }

    catch ( Exception ex )
    {
      JOptionPane.showMessageDialog(
          null,
          "Fehler beim MAX-Zugriff auf die Tabelle Kuchen: " + ex.getMessage(),
          "db-Fehler",
          JOptionPane.ERROR_MESSAGE
          );
    }

    return retValue;
  }

  /**
   * 
   * @param ID
   * @return ist (noch) vorhanden?
   */
  public static boolean isKuchenVorhanden( int ID )
  {
    String sql = " SELECT COUNT(*) ";
          sql += " FROM kuchen";
          sql += " WHERE ID = ? ";

    PreparedStatement prepStatement = DBConnection.prepareStatement( sql );
    ResultSet result = null;
    boolean retValue = false;

    try
    {
      prepStatement.setInt( 1, ID );

      result = prepStatement.executeQuery();

      if ( result != null )
      {
        result.next();
        retValue = ( result.getInt( 1 ) > 0 );
      }
    }

    catch ( Exception ex )
    {
      JOptionPane.showMessageDialog(
          null,
          "Fehler beim Exist-Zugriff auf die Tabelle Kuchen: " + ex.getMessage(),
          "db-Fehler",
          JOptionPane.ERROR_MESSAGE
          );
    }

    return retValue;
  }

  /**
   * 
   * @return Anzahl der vorhandenen Kuchen Der technische Satz ID wird nicht mitgezählt
   */
  public static int getKuchenAnzahl()
  {
    String sql = " SELECT COUNT(*) ";
          sql += " FROM kuchen ";
          sql += " WHERE ID > 0 ";

    PreparedStatement prepStatement = DBConnection.prepareStatement( sql );
    ResultSet result = null;
    int retValue = -1;

    try
    {
      result = prepStatement.executeQuery();

      if ( result != null )
      {
        result.next();
        retValue = result.getInt( 1 );
      }
    }

    catch ( Exception ex )
    {
      JOptionPane.showMessageDialog(
          null,
          "Fehler beim Count-Zugriff auf die Tabelle Kuchen: " + ex.getMessage(),
          "db-Fehler",
          JOptionPane.ERROR_MESSAGE
          );
    }

    return retValue;
  }

  /**
   * 
   * @param ID
   * @return Kuchen-Objekt zur ID
   */
  public static Kuchen getKuchen( int ID )
  {
    String sql = " SELECT ID, anbieter, sorte, kurzkuchen, beschreibung, abgabedatum, ";
          sql += " anzahl, preis, diabetikergeeignet, letzterzugriff ";
          sql += " FROM kuchen ";
          sql += " WHERE ID = ? ";

    PreparedStatement prepStatement = DBConnection.prepareStatement( sql );
    ResultSet result = null;
    Kuchen retValue = new Kuchen();

    try
    {
      prepStatement.setInt( 1, ID );

      result = prepStatement.executeQuery();

      if ( result != null )
      {
        result.next();
        retValue.setID( result.getInt( 1 ) );
        retValue.setAnbieter( result.getString( 2 ) );
        retValue.setSorte( result.getInt( 3 ) );
        retValue.setKurzkuchen( result.getString( 4 ) );
        Object test = result.getObject( 5 );
        if ( test != null )
          retValue.setBeschreibung( result.getString( 5 ) );
        retValue.setAbgabedatum( DatenPlausi.ef2df( result.getString( 6 ) ) );
        retValue.setAnzahl( result.getInt( 7 ) );
        retValue.setPreis( result.getDouble( 8 ) );
        retValue.setDiabetikergeeignet( result.getBoolean( 9 ) );
        retValue.setLetzterzugriff( result.getString( 10 ) );
      }
    }

    catch ( Exception ex )
    {
      JOptionPane.showMessageDialog(
          null,
          "Fehler beim ID-Zugriff auf die Tabelle Kuchen: " + ex.getMessage(),
          "db-Fehler",
          JOptionPane.ERROR_MESSAGE
          );
    }

    return retValue;
  }

  /**
   * 
   * @param ID
   * @return Vorrat (Anzahl) vom Kuchen zur ID
   */
  public static int getAnzahl( int ID )
  {
    String sql = " SELECT anzahl ";
          sql += " FROM kuchen ";
          sql += " WHERE ID = ? ";

    PreparedStatement prepStatement = DBConnection.prepareStatement( sql );
    ResultSet result = null;
    int retValue = -1;

    try
    {
      prepStatement.setInt( 1, ID );

      result = prepStatement.executeQuery();

      if ( result != null )
      {
        result.next();
        retValue = result.getInt( 1 );
      }
    }

    catch ( Exception ex )
    {
      JOptionPane.showMessageDialog(
          null,
          "Fehler beim Anzahl-Zugriff auf die Tabelle Kuchen: " + ex.getMessage(),
          "db-Fehler",
          JOptionPane.ERROR_MESSAGE
          );
    }

    return retValue;
  }

  /**
   * Setze den Vorrat (Anzahl) des Kuchens mit der ID neu
   * 
   * @param ID
   * @param anzahl
   * @return erfolgreich
   */
  public static boolean setAnzahl( int ID, int anzahl )
  {
    String sql = " UPDATE kuchen ";
          sql += " SET anzahl = ?, ";
          sql += " letzterzugriff = CURRENT_TIMESTAMP ";
          sql += " WHERE ID = ? ";

    PreparedStatement prepStatement = DBConnection.prepareStatement( sql );
    boolean retValue = false;

    try
    {
      prepStatement.setInt( 1, anzahl );
      prepStatement.setInt( 2, ID );

      prepStatement.executeUpdate();

      retValue = true;
    }

    catch ( Exception ex )
    {
      JOptionPane.showMessageDialog(
          null,
          "Fehler beim Update/Anzahl-Zugriff auf die Tabelle Kuchen: " + ex.getMessage(),
          "db-Fehler",
          JOptionPane.ERROR_MESSAGE
          );
    }

    return retValue;
  }

  /**
   * 
   * @param ID
   * @return Preis vom Kuchen zur ID
   */
  public static double getPreis( int ID )
  {
    String sql = " SELECT preis ";
          sql += " FROM kuchen ";
          sql += " WHERE ID = ? ";

    PreparedStatement prepStatement = DBConnection.prepareStatement( sql );
    ResultSet result = null;
    double retValue = -1;

    try
    {
      prepStatement.setInt( 1, ID );

      result = prepStatement.executeQuery();

      if ( result != null )
      {
        result.next();
        retValue = result.getDouble( 1 );
      }
    }

    catch ( Exception ex )
    {
      JOptionPane.showMessageDialog(
          null,
          "Fehler beim Preis-Zugriff auf die Tabelle Kuchen: " + ex.getMessage(),
          "db-Fehler",
          JOptionPane.ERROR_MESSAGE
          );
    }

    return retValue;
  }

  /**
   * 
   * @return Liste aller Kuchen mit <ID und Name>
   */
  public static ArrayList<ListItem> getKuchenListe()
  {
    String sql = " SELECT ID, kurzkuchen ";
          sql += " FROM kuchenview ";
    //    sql += " WHERE ID > 0 ";

    //Auch wenn keine Parameter zu versorgen sind, 
    //gebe ich dem PreparedStatement den Vorzug

    PreparedStatement prepStatement = DBConnection.prepareStatement( sql );
    ResultSet result = null;
    ArrayList<ListItem> retValue = new ArrayList<ListItem>();

    try
    {
      result = prepStatement.executeQuery();

      while ( result.next() )
      {
        ListItem listitem = new ListItem( result.getInt( 1 ), result.getString( 2 ) );
        retValue.add( listitem );
      }
    }

    catch ( Exception ex )
    {
      JOptionPane.showMessageDialog(
          null,
          "Fehler beim Liste-Zugriff auf die View KuchenView: " + ex.getMessage(),
          "db-Fehler",
          JOptionPane.ERROR_MESSAGE
          );
    }

    return retValue;
  }

  /**
   * 
   * @return Liste aller Kuchen-Objekte
   */
  public static ArrayList<Kuchen> getKuchenTabelle()
  {
    String sql = " SELECT ID, anbieter, sorte, kurzkuchen, beschreibung, abgabedatum, ";
          sql += " anzahl, preis, diabetikergeeignet, letzterzugriff ";
          sql += " FROM kuchen ";
    //    sql += " WHERE ID > 0 ";

    PreparedStatement prepStatement = DBConnection.prepareStatement( sql );
    ResultSet result = null;
    ArrayList<Kuchen> retValue = new ArrayList<Kuchen>();

    try
    {
      result = prepStatement.executeQuery();

      while ( result.next() )
      {
        Kuchen kuchen = new Kuchen();
        kuchen.setID( result.getInt( 1 ) );
        kuchen.setAnbieter( result.getString( 2 ) );
        kuchen.setSorte( result.getInt( 3 ) );
        kuchen.setKurzkuchen( result.getString( 4 ) );
        Object test = result.getObject( 5 );
        if ( test != null )
          kuchen.setBeschreibung( result.getString( 5 ) );
        kuchen.setAbgabedatum( DatenPlausi.ef2df( result.getString( 6 ) ) );
        kuchen.setAnzahl( result.getInt( 7 ) );
        kuchen.setPreis( result.getDouble( 8 ) );
        kuchen.setDiabetikergeeignet( result.getBoolean( 9 ) );
        kuchen.setLetzterzugriff( result.getString( 10 ) );
        retValue.add( kuchen );
      }
    }

    catch ( Exception ex )
    {
      JOptionPane.showMessageDialog(
          null,
          "Fehler beim Tabelle-Zugriff auf die Tabelle Kuchen: " + ex.getMessage(),
          "db-Fehler",
          JOptionPane.ERROR_MESSAGE
          );
    }

    return retValue;
  }

  /**
   * 
   * @return Liste aller Kuchen als ResultSet für die JTable Diese kann die ResultSet-Felder selber
   *         und besser (da anonym) auswerten
   */
  public static ResultSet getKuchenSet()
  {
    String sql = " SELECT ID ID, ";
          sql += " kurzkuchen AS Name, anbieter AS Anbieter, sorte AS Sorte, ";
          sql += " anzahl AS Anzahl, preis AS Preis ";
          sql += " FROM kuchenview ";
          sql += " WHERE ID > 0 ";

    PreparedStatement prepStatement = DBConnection.prepareStatement( sql );
    ResultSet retValue = null;

    try
    {
      retValue = prepStatement.executeQuery();
    }

    catch ( Exception ex )
    {
      JOptionPane.showMessageDialog(
          null,
          "Fehler beim RSet-Zugriff auf die View KuchenView: " + ex.getMessage(),
          "db-Fehler",
          JOptionPane.ERROR_MESSAGE
          );
    }

    return retValue;
  }

  /**
   * 
   * @param kuchen
   * @return ID des erzeugten und eingefügten neuen Kuchens
   */
  public static int insertKuchen( Kuchen kuchen )
  {
    String sql = " INSERT INTO kuchen ";
          sql += " (anbieter, beschreibung, abgabedatum, ";
          sql += " anzahl, preis, diabetikergeeignet, ";
          sql += " sorte, kurzkuchen, letzterzugriff ) ";
          sql += " VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP )";

    PreparedStatement prepStatement = DBConnection.prepareStatement( sql );
    int retValue = -1;

    try
    {
      prepStatement.setString( 1, kuchen.getAnbieter() );
      prepStatement.setString( 2, kuchen.getBeschreibung() );
      prepStatement.setString( 3, DatenPlausi.df2ef( kuchen.getAbgabedatum() ) );
      prepStatement.setInt( 4, kuchen.getAnzahl() );
      prepStatement.setDouble( 5, kuchen.getPreis() );
      prepStatement.setBoolean( 6, kuchen.isDiabetikergeeignet() );
      prepStatement.setInt( 7, kuchen.getSorte() );
      prepStatement.setString( 8, kuchen.getKurzkuchen() );

      DBConnection.beginTransaction();

      prepStatement.executeUpdate();

      //Wichtig! In der laufenden Transaktion nach dem gerade eingefügten
      //Satz fahnden
      retValue = getMaxID();

      DBConnection.commitTransaction();
    }

    catch ( Exception ex )
    {
      DBConnection.rollbackTransaction();

      JOptionPane.showMessageDialog(
          null,
          "Fehler beim Insert-Zugriff auf die Tabelle Kuchen: " + ex.getMessage(),
          "db-Fehler",
          JOptionPane.ERROR_MESSAGE
          );
    }

    return retValue;
  }

  /**
   * 
   * @param ID
   * @param kuchen
   * @return erfolgreich
   */
  public static boolean updateKuchen( int ID, Kuchen kuchen )
  {
    String sql = " UPDATE kuchen ";
          sql += " SET anbieter = ?, beschreibung = ?, abgabedatum = ?, ";
          sql += " anzahl = ?, preis = ?, diabetikergeeignet = ?, ";
          sql += " sorte = ?, kurzkuchen = ?, ";
          sql += " letzterzugriff = CURRENT_TIMESTAMP ";
          sql += " WHERE ID = ? ";

    PreparedStatement prepStatement = DBConnection.prepareStatement( sql );
    boolean retValue = false;

    try
    {
      prepStatement.setString( 1, kuchen.getAnbieter() );
      prepStatement.setString( 2, kuchen.getBeschreibung() );
      prepStatement.setString( 3, DatenPlausi.df2ef( kuchen.getAbgabedatum() ) );
      prepStatement.setInt( 4, kuchen.getAnzahl() );
      prepStatement.setDouble( 5, kuchen.getPreis() );
      prepStatement.setBoolean( 6, kuchen.isDiabetikergeeignet() );
      prepStatement.setInt( 7, kuchen.getSorte() );
      prepStatement.setString( 8, kuchen.getKurzkuchen() );
      prepStatement.setInt( 9, ID );

      DBConnection.beginTransaction();

      prepStatement.executeUpdate();

      DBConnection.commitTransaction();

      retValue = true;
    }

    catch ( Exception ex )
    {
      DBConnection.rollbackTransaction();

      JOptionPane.showMessageDialog(
          null,
          "Fehler beim Update-Zugriff auf die Tabelle Kuchen: " + ex.getMessage(),
          "db-Fehler",
          JOptionPane.ERROR_MESSAGE
          );
    }

    return retValue;
  }

  /**
   * 
   * @param ID
   * @return erfolgreich
   */
  public static boolean deleteKuchen( int ID )
  {
    String sql = " DELETE FROM kuchen ";
          sql += " WHERE ID = ? ";

    PreparedStatement prepStatement = DBConnection.prepareStatement( sql );
    boolean retValue = false;

    try
    {
      prepStatement.setInt( 1, ID );

      DBConnection.beginTransaction();

      prepStatement.executeUpdate();

      DBConnection.commitTransaction();

      retValue = true;
    }

    catch ( Exception ex )
    {
      DBConnection.rollbackTransaction();

      JOptionPane.showMessageDialog(
          null,
          "Fehler beim Delete-Zugriff auf die Tabelle Kuchen: " + ex.getMessage(),
          "db-Fehler",
          JOptionPane.ERROR_MESSAGE
          );
    }

    return retValue;
  }

  /**
   * Leeren der Kuchen-Tabelle
   * 
   * @return erfolgreich
   */
  public static boolean zapKuchen()
  {
    //Entwurfsentscheidung: wir lassen den technischen 0-Satz mal leben...
    String sql = " DELETE FROM kuchen ";
          sql += " WHERE ID > 0 ";

    boolean retValue = false;

    try
    {
      DBConnection.beginTransaction();

      DBConnection.executeNoneQuery( sql );

      DBConnection.commitTransaction();

      retValue = true;
    }

    catch ( Exception ex )
    {
      DBConnection.rollbackTransaction();

      JOptionPane.showMessageDialog(
          null,
          "Fehler beim ZAP-Zugriff auf die Tabelle Kuchen: " + ex.getMessage(),
          "db-Fehler",
          JOptionPane.ERROR_MESSAGE
          );
    }

    return retValue;
  }
}
