using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;

public class KuchenDB
{
	SqlCommand sqlAbfrage;

    public KuchenDB(SqlCommand sqlAbfrage)
    {
        this.sqlAbfrage = sqlAbfrage;
		init();
	}

	KuchenDB()
	{
		init();
	}

	~KuchenDB()
	{
	}

	void init()
	{	
		angebotsliste = new List<String>();
		isChanged = true;
		dictIndexFromId = new Dictionary<int, int>();
		dictIdFromIndex = new Dictionary<int, int>();
	}

	//Liste wird nach Insert/Delete gelöscht
	//Liste wird am Anfang sowie bei Bedarf neu aufgebaut
	List<String> angebotsliste;
    public bool isChanged;

	Dictionary<int, int> dictIndexFromId;
	Dictionary<int, int> dictIdFromIndex;

	void erzwingeListenaufbau()
	{
		isChanged = true;
		angebotsliste.Clear();
		dictIndexFromId.Clear();
		dictIdFromIndex.Clear();
	}

    public List<String> getList()
	{
		isChanged = false;
		int counter = 0;

		if (angebotsliste.Count == 0)
		{
			sqlAbfrage.CommandText = "SELECT ID, anbieter, kurzkuchen "+
									  "FROM KuchenView ORDER BY 1 ASC";

			SqlDataReader aktCursor = sqlAbfrage.ExecuteReader();

			while (aktCursor.Read())
			{
				String tempanbieter = aktCursor.GetString(1);
				String tempkuchen = aktCursor.GetString(2);
				int tempID = aktCursor.GetInt32(0);

				isChanged = true;

				if (tempID > 0)
				{
					angebotsliste.Add(tempkuchen + ", " + tempanbieter);
				}
				else
				{
					angebotsliste.Add(tempkuchen);
				}

				dictIndexFromId.Add(tempID, counter);
				dictIdFromIndex.Add(counter, tempID);
				counter++;
			}

			aktCursor.Close();
		}
	
		return angebotsliste;
	}

    public int getIdFromIndex(int index)
	{
		if (dictIdFromIndex.ContainsKey(index))
		{
			int tempId = dictIdFromIndex[index];
			return tempId;
		}
		else
		{
			return 0;
		}
	}

    public int getIndexFromId(int id)
	{
		if (dictIndexFromId.ContainsKey(id))
		{
			int tempIndex = dictIndexFromId[id];
			return tempIndex;
		}
		else
		{
			return 0;
		}
	}

    public int getVorrat(int aktid)
	{
		sqlAbfrage.CommandText =
			"SELECT anzahl FROM Kuchen " +
			"WHERE id = @kuchenid;";

		sqlAbfrage.Parameters.Clear();
		sqlAbfrage.Parameters.AddWithValue("kuchenid", aktid);

		Object aktSQL = sqlAbfrage.ExecuteScalar();
		if (aktSQL != null)
		{
			int tempanzahl = Convert.ToInt32(aktSQL);
			return tempanzahl;
		}

		return 0;
	}

    public double getPreis(int aktid)
	{
		sqlAbfrage.CommandText =
			"SELECT preis FROM Kuchen " +
			"WHERE id = @kuchenid;";

		sqlAbfrage.Parameters.Clear();
		sqlAbfrage.Parameters.AddWithValue("kuchenid", aktid);

		Object aktSQL = sqlAbfrage.ExecuteScalar();
		if (aktSQL != null)
		{
			double temppreis = Convert.ToDouble(aktSQL);
			return temppreis;
		}

		return 0;
	}

    public int getSorte(int aktid)
	{
		sqlAbfrage.CommandText =
			"SELECT sorte FROM Kuchen " +
			"WHERE id = @kuchenid;";

		sqlAbfrage.Parameters.Clear();

		SqlParameter parameter = new SqlParameter();
		parameter.Value = aktid;
		parameter.SqlDbType = SqlDbType.Int;
		parameter.ParameterName = "@kuchenid";
		sqlAbfrage.Parameters.Add(parameter);

		Object aktSQL = sqlAbfrage.ExecuteScalar();
		if (aktSQL != null)
		{
			int tempsorte = Convert.ToInt32(aktSQL);
			return tempsorte;
		}

		return 0;
	}

    public void update(Kuchen aktkuchen)
	{
		aktkuchen.Letzterzugriff = DateTime.Now;

		//Ich habe an dieser Stelle wirklich 2 Tage lang debuggt und gesucht,
		//warum die Variante mit dem sqlAbfrage.Parameters.AddWithValue("@id", id);
		//nicht funktioniert in C++ 
		//Leider gibt es auch keine qualifizierte Fehlermeldung wie z.B. SQLSTATE in DB2
		//Laut Indernett Foren liegt das Problem bei Access und/oder beim OLEDB :-(*/
		
		//sqlAbfrage.Parameters.Clear();
		//sqlAbfrage.Parameters.AddWithValue("@id", aktkuchen.Id);
		//sqlAbfrage.Parameters.AddWithValue("@anbieter", aktkuchen.Anbieter);
		//sqlAbfrage.Parameters.AddWithValue("@sorte", aktkuchen.Sorte);
		//sqlAbfrage.Parameters.AddWithValue("@kurzkuchen", aktkuchen.Kurzkuchen);
		//if (aktkuchen.Beschreibung.Length != 0)
		//{
		//	sqlAbfrage.Parameters.AddWithValue("@beschreibung", aktkuchen.Beschreibung);
		//}
		//else
		//{
		//	sqlAbfrage.Parameters.AddWithValue("@beschreibung", DBNull.Value);
		//}
		//sqlAbfrage.Parameters.AddWithValue("@abgabedatum", aktkuchen.Abgabedatum);
		//sqlAbfrage.Parameters.AddWithValue("@anzahl", aktkuchen.Anzahl);
		//sqlAbfrage.Parameters.AddWithValue("@diabetikergeeignet", aktkuchen.Diabetikergeeignet);
		//sqlAbfrage.Parameters.AddWithValue("@letzterzugriff", aktkuchen.Letzterzugriff);
		//
		//sqlAbfrage.CommandText =
		//	"UPDATE Kuchen SET " +
		//	"anbieter = @anbieter, " +
		//	"sorte = @sorte, " +
		//	"kurzkuchen = @kurzkuchen, " +
		//	"beschreibung = @beschreibung, " +
		//	"abgabedatum = @abgabedatum, " +
		//	"anzahl = @anzahl, " +
		//	"diabetikergeeignet = @diabetikergeeignet, " +
		//	"letzterzugriff = @letzterzugriff " +
		//	"WHERE id = @id";
		//
		//int ergebnis1 = sqlAbfrage.ExecuteNonQuery();

		sqlAbfrage.CommandText =
			"UPDATE Kuchen SET " +
			"anbieter = " + "'" + aktkuchen.Anbieter + "'" + ", " +
			"sorte = " + aktkuchen.Sorte.ToString() + ", " +
			"kurzkuchen = " + "'" + aktkuchen.Kurzkuchen + "'" + ", " +
			"beschreibung = " + "'" + aktkuchen.Beschreibung + "'" + ", " +
			"abgabedatum =  " + "cast('" + aktkuchen.Abgabedatum.ToString() + "' as datetime)" + ", " +
			"anzahl = " + aktkuchen.Anzahl.ToString() + ", " +
			"preis = " + String.Format("{0:F2}", aktkuchen.Preis).Replace(',', '.') + ", " +
			"diabetikergeeignet = " + "'" + aktkuchen.Diabetikergeeignet.ToString() + "'" + ", " +
			"letzterzugriff =  " + "cast('" + aktkuchen.Letzterzugriff.ToString() + "' as datetime) " +
			"WHERE id = " + aktkuchen.Id.ToString() + ";";

		int ergebnis2 = sqlAbfrage.ExecuteNonQuery();
	}

    public int insert(Kuchen neukuchen)
	{
		neukuchen.Letzterzugriff = DateTime.Now;

		sqlAbfrage.CommandText =
			"INSERT INTO Kuchen " +
			"(anbieter, sorte, kurzkuchen, beschreibung, abgabedatum, anzahl, preis, diabetikergeeignet, letzterzugriff) " + 
			"VALUES (" + 
			"'" + neukuchen.Anbieter + "'" + ", " + 
			neukuchen.Sorte.ToString() + ", " + 
			"'" + neukuchen.Kurzkuchen + "'" + ", " +
			"'" + neukuchen.Beschreibung + "'" + ", " +
			"cast('" + neukuchen.Abgabedatum.ToString() + "' as datetime)" + ", " +
			neukuchen.Anzahl.ToString() + ", " + 
			String.Format("{0:F2}", neukuchen.Preis).Replace(',', '.') + ", " +
			"'" + neukuchen.Diabetikergeeignet.ToString() + "'" + ", " + 
			"cast('" + neukuchen.Letzterzugriff.ToString() + "' as datetime)" + 
			");";

		sqlAbfrage.ExecuteNonQuery();

		//Lösche die angebotsliste und die dictionary, sie werden gleich wieder aufgebaut :-)
		erzwingeListenaufbau();

		int neueID = 0;

		//da die neuvergebene ID nur für den Cursor der dataGridView benötigt wird
		//und auch 0 ok wäre, machen wir das hier nicht so wissenschaftlich
		//über alle Attribute, sondern nur über Erstellung und letzten Zugriff
		sqlAbfrage.CommandText =
			"SELECT id FROM Kuchen " +
			"WHERE abgabedatum = " + "cast('" + neukuchen.Abgabedatum.ToString() + "' as datetime)" +
			" AND  letzterzugriff = " + "cast('" + neukuchen.Letzterzugriff.ToString() + "' as datetime);";
				
		Object aktSQL = sqlAbfrage.ExecuteScalar();
		if (aktSQL != null)
		{
			neueID = Convert.ToInt32(aktSQL);
		}

		return neueID;
	}

    public void del(int aktid)
	{
		sqlAbfrage.CommandText =
			"DELETE " +
			"FROM Kuchen " +
			"WHERE id = @id;";

		sqlAbfrage.Parameters.Clear();
		sqlAbfrage.Parameters.AddWithValue("@id", aktid);

		sqlAbfrage.ExecuteNonQuery();

		//Lösche die angebotsliste und die dictionary, sie werden gleich wieder aufgebaut :-)
		erzwingeListenaufbau();
	}

    public Kuchen get(int aktid)
	{
		Kuchen aktKuchen = new Kuchen();

		aktKuchen.Id = aktid;

		sqlAbfrage.CommandText =
			"SELECT anbieter, sorte, kurzkuchen, beschreibung, abgabedatum, anzahl, preis, diabetikergeeignet " +
			"FROM Kuchen " +
			"WHERE id = @id;";

		sqlAbfrage.Parameters.Clear();
		sqlAbfrage.Parameters.AddWithValue("@id", aktid);

	    SqlDataReader aktCursor = sqlAbfrage.ExecuteReader();

		aktCursor.Read();

		aktKuchen.Anbieter = aktCursor.GetString(0);
		aktKuchen.Sorte = aktCursor.GetInt32(1);
		aktKuchen.Kurzkuchen = aktCursor.GetString(2);

		Object tempbeschreibung = aktCursor.GetValue(3);
		if (tempbeschreibung != DBNull.Value)
		{
			aktKuchen.Beschreibung = aktCursor.GetString(3);
		}

		aktKuchen.Abgabedatum = aktCursor.GetDateTime(4);

		aktKuchen.Anzahl = aktCursor.GetInt32(5);
		aktKuchen.Preis = (double) aktCursor.GetDecimal(6);
		aktKuchen.Diabetikergeeignet = aktCursor.GetBoolean(7);

		aktCursor.Close();

		return aktKuchen;
	}

    public DataTable getTable()
	{
		DataTable kuchenTabelle = new DataTable();

		kuchenTabelle.Columns.Add("ID", Type.GetType("System.Int32"));
		kuchenTabelle.Columns.Add("Anbieter", Type.GetType("System.String"));
		kuchenTabelle.Columns.Add("Kurzname", Type.GetType("System.String"));
		kuchenTabelle.Columns.Add("Anzahl", Type.GetType("System.Int32"));
		kuchenTabelle.Columns.Add("Preis", Type.GetType("System.String"));
		kuchenTabelle.Columns.Add("LetzterZugriff", Type.GetType("System.DateTime"));

		sqlAbfrage.CommandText =
			"SELECT ID, Anbieter, Kurzkuchen, Anzahl, Preis, Letzterzugriff " +
			"FROM Kuchen WHERE id > 0;";

		SqlDataReader aktCursor = sqlAbfrage.ExecuteReader();

		while (aktCursor.Read())
		{
			DataRow zeile = kuchenTabelle.NewRow();

			double tempdouble = (double) aktCursor.GetDecimal(4);
			String temppreis = String.Format("{0:F2}", tempdouble).Replace(',', '.');

			zeile["ID"] = aktCursor.GetInt32(0);
			zeile["Anbieter"] = aktCursor.GetString(1);
			zeile["Kurzname"] = aktCursor.GetString(2);
			zeile["Anzahl"] = aktCursor.GetInt32(3);
			zeile["Preis"] = temppreis + " €";
			zeile["LetzterZugriff"] = aktCursor.GetDateTime(5);

			kuchenTabelle.Rows.Add(zeile);
		}

		aktCursor.Close();

		return kuchenTabelle;
	}

    public DataTable getTable(String suchmaske)
	{
		DataTable kuchenTabelle = new DataTable();
		String suchstring;

		kuchenTabelle.Columns.Add("ID", Type.GetType("System.Int32"));
		kuchenTabelle.Columns.Add("Anbieter", Type.GetType("System.String"));
		kuchenTabelle.Columns.Add("Kurzname", Type.GetType("System.String"));
		kuchenTabelle.Columns.Add("Anzahl", Type.GetType("System.Int32"));
		kuchenTabelle.Columns.Add("Preis", Type.GetType("System.String"));
		kuchenTabelle.Columns.Add("LetzterZugriff", Type.GetType("System.DateTime"));

		//hier wird die View gelesen, um Backwarensorte mit in den Suchstring zu bekommen
		//"true" und "false" stören aber beim Filter nur, das Datum ist bewußt verkürzt
		sqlAbfrage.CommandText =
			"SELECT ID, anbieter, backwarensorte, kurzkuchen, beschreibung, abgabedatum, anzahl, preis, diabetikergeeignet, letzterzugriff " +
			"FROM KuchenView WHERE id > 0;";

		SqlDataReader aktCursor = sqlAbfrage.ExecuteReader();

		while (aktCursor.Read())
		{	
			Object tempObj = aktCursor.GetValue(4);
			String tempbeschreibung = "";
			if (tempObj != DBNull.Value)
			{
				tempbeschreibung = aktCursor.GetString(4);
			}
			
			double tempdouble = (double) aktCursor.GetDecimal(7);
			String temppreis = String.Format("{0:F2}", tempdouble).Replace(',', '.');

			suchstring = aktCursor.GetString(1) +
				aktCursor.GetString(2) +
				aktCursor.GetString(3) +
				tempbeschreibung +	
				temppreis +
				Convert.ToString(aktCursor.GetDateTime(5)).Substring(0, 10) +
				Convert.ToString(aktCursor.GetInt32(6));

			// wenn der Suchstring irgendwie vorkommt?
			// das schließt einen leeren Suchstring implizit mit ein
			if (suchstring.Contains(suchmaske))
			{
				DataRow zeile = kuchenTabelle.NewRow();

				zeile["ID"] = aktCursor.GetInt32(0);
				zeile["Anbieter"] = aktCursor.GetString(1);
				zeile["Kurzname"] = aktCursor.GetString(3);
				zeile["Anzahl"] = aktCursor.GetInt32(6);
				zeile["Preis"] = temppreis + " €";
				zeile["LetzterZugriff"] = aktCursor.GetDateTime(9);

				kuchenTabelle.Rows.Add(zeile);
			}
		}

		aktCursor.Close();

		return kuchenTabelle;
	}

    public void setVorrat(int aktid, int veraenderung)
	{
		int wertalt = getVorrat(aktid);
		int wertneu = wertalt + veraenderung;
		DateTime letzterzugriff = DateTime.Now;

		//auch hier geht die AddWithValue Variante beim Update nicht 
		//(kein Syntaxfehler aber trotzdem 0 Zeilen betroffen :-( 
		//sqlAbfrage.Parameters.Clear();
		//sqlAbfrage.Parameters.AddWithValue("@id", aktid);
		//sqlAbfrage.Parameters.AddWithValue("@anzahl", wertneu);
		//sqlAbfrage.Parameters.AddWithValue("@letzterzugriff", letzterzugriff);
		
		//sqlAbfrage.CommandText =
		//	"UPDATE Kuchen SET " +
		//	"anzahl = @anzahl, " +
		//	"letzterzugriff = @letzterzugriff " +
		//	"WHERE id = @id";
		
		//int ergebnis1 = sqlAbfrage.ExecuteNonQuery();

		sqlAbfrage.CommandText =
			"UPDATE Kuchen SET " +
			"anzahl = " + wertneu.ToString() + ", " +
			"letzterzugriff =  " + "cast('" + letzterzugriff.ToString() + "' as datetime) " +
			"WHERE id = " + aktid.ToString() + ";";

		int ergebnis2 = sqlAbfrage.ExecuteNonQuery();
	}
};