using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using System.Data.OleDb;
using System.Data.Common;

public partial class DataEditor : System.Web.UI.Page
{
   OleDbConnection _conn = null;

    /// <summary>
    /// Procedura obsługi ładowania strony
    /// </summary>
    protected void Page_Load(object sender, EventArgs e)
    {
      if (!IsPostBack)
      {
         LoadAllBooks();
         panBook.Visible = false;
      }
    }

    /// <summary>
    /// Dołączanie danych do listy rozwijanej z książkami
    /// </summary>
    private void LoadAllBooks()
    {
      OleDbDataReader reader = GetReader(GetBookSql(),null,true);
      lboxBooks.DataSource = reader;
      lboxBooks.DataBind();
      reader.Close();
    }

    /// <summary>
    /// Zwraca ciąg SQL z wybranymi informacjami o książce
    /// </summary>
    private string GetBookSql()
    {
      return "SELECT ISBN,Title,YearPublished,PublisherId FROM Books";
    }

/// <summary>
/// Obsługa wyboru książki
/// </summary>
protected void SelectBooks(object sender, EventArgs e)
{
   // pokazanie panelu
   panBook.Visible = true;

   // odczytanie numeru isbn książki wybranej przez użytkownika
   string sId = lboxBooks.SelectedValue;

   // tworzenie zapytania sql dla wybranego numeru isbn
   string sql = GetBookSql();
   sql += " WHERE ISBN=@Id";

   // utworzenie parametrów zapytania
   OleDbParameter[] param = {
      new OleDbParameter("@ID", sId)
   };

   // pobranie obiektu odczytu danych zawierających dane książki
   OleDbDataReader reader = GetReader(sql, param, true);
   
   try
   {
      // jeżeli mamy obiekt odczytu, to kontynuujemy
      if (reader != null)
      {
         // ustawienie kursora na pierwszym rekordzie
         if (reader.Read())
         {
            // pobranie kolumny danych z obiektu
            // korzystając z nazw pól lub numerów
            // i przypisanie ich do pól formularza
            txtIsbn.Text = (string)reader["ISBN"];

            if (!reader.IsDBNull(1))
               txtTitle.Text = reader.GetString(1);
            else
               txtTitle.Text = "";

            if (!reader.IsDBNull(2))
               txtYear.Text = reader.GetInt32(2).ToString();
            else
               txtYear.Text = "";

            // identyfikator wydawcy jest nieco bardziej skomplikowany, 
             // ponieważ mamy wartość w liście rozwijanej
            int publisherId = reader.GetInt32(3);
            MakePublisherDropDown(publisherId);

            labUpdate.Text = "";
         }
      }
   }
   catch (Exception ex)
   {
      labMsg.Text = "[lboxBooks_SelectedIndexChanged] ";
      labMsg.Text += "Wystąpił błąd podczas dostępu do bazy danych";
      labMsg.Text += "<br/>" + ex.Message;
   }
   finally
   {
      reader.Close();
   }
}

    /// <summary>
    /// Dołączanie danych do listy wydawców,
    /// a następnie zaznaczenie elementu listy na podstawie 
    /// przekazanej wartości publisherId 
    /// </summary>
    private void MakePublisherDropDown(int publisherId)
    {
      string sql = "SELECT PublisherId, PublisherName ";
      sql += " FROM Publishers ORDER BY PublisherName";

      OleDbDataReader reader = GetReader(sql, null, false);
      drpPublisher.DataSource = reader;
      drpPublisher.DataBind();

      // użycie przekazanej wartości publisherId do zaznaczenia elementu listy
      drpPublisher.SelectedValue = publisherId.ToString();
      reader.Close();
    }

    /// <summary>
    /// Procedura obsługi aktualizacji danych ksiażki 
    /// </summary>
    protected void UpdateBook(object sender, EventArgs e)
    {
      // odczytanie numeru isbn książki wybranej przez użytkownika
      string sId = lboxBooks.SelectedValue;

      // tworzenie sql dla podanego numeru isbn
      string sql = "UPDATE Books SET Title=@title, YearPublished=@yearPub, PublisherId=@pubId";
      sql += " WHERE ISBN=@isbn";
      labUpdate.Text = sql;

      // pobranie połączenia do bazy danych
      OleDbConnection conn = GetConnection();

      try
      {
        // utworzenie obiektu polecenia
        OleDbCommand cmd = new OleDbCommand(sql, conn);

        // dodanie parametrów
        cmd.Parameters.Add(new OleDbParameter("@title", txtTitle.Text));
        cmd.Parameters.Add(new OleDbParameter("@yearPub", txtYear.Text));
        // można również użyć metody AddWithValue jako alternatywy dla powyższych
        cmd.Parameters.AddWithValue("@pubId", drpPublisher.SelectedValue);
        cmd.Parameters.AddWithValue("@isbn", txtIsbn.Text);

        // wykonanie polecenia 
        cmd.ExecuteNonQuery();

        labUpdate.Text = "Udana aktualizacja rekordu";
      }
      catch (Exception ex)
      {
        labMsg.Text = "[btnUpdate_Click] ";
        labMsg.Text += "Podczas dostępu do bazy danych wystąpił błąd";
        labMsg.Text += "<br/>" + ex.Message;
      }
      finally
      {
        conn.Close();
        conn = null;
      }
    }

    /// <summary>
    /// Pobiera obiekt odczytu danych dla przekazanego ciągu SQL
    /// </summary>
    /// <param name="sql">Zawiera instrukcję SQL polecenia</param>
    /// <param name="param">Opcjonalne parametry dodawane do polecenia</param>
    /// <param name="addClose">jeżeli ma wartość truem zamyka obiekt odczytu</param>
    /// <returns>obiekt odczytu danych zawierający żądane dane SQL</returns>
    private OleDbDataReader GetReader(string sql, OleDbParameter[] parameters, bool addClose)
    {
     // pobranie połączenia do bazy danych
     OleDbConnection conn = GetConnection();
     OleDbDataReader reader = null;
     try
     {
       // tworzenie obiektu połączenia dla przekazanego SQL
       OleDbCommand cmd = new OleDbCommand(sql, conn);

       // dodanie parametrów, jeżeli zostały przekazane
       if (parameters != null)
       {
         foreach (OleDbParameter param in parameters)
           cmd.Parameters.Add(param);
       }

       // ComandBehavior.CloseConnection wskazuje, że 
       // połączenie zostanie zamknięte po zakończeniu odczytu danych
       if (addClose)
         reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
       else
         reader = cmd.ExecuteReader();
     }
     catch (Exception ex)
     {
       labMsg.Text = "[GetReader] Wystąpił błąd w czasie dostępu do bazy danych";
       labMsg.Text += "<br/>" + ex.Message;

       if (reader != null)
         reader.Close();
       if (conn != null)
         conn.Close();
     }

     // Zwracanie wynikowego obiektu odczytu.
     return reader;
    }

    /// <summary>
    /// Zwraca obiekt połączenia do bazy danych
    /// </summary>
    /// <returns></returns>
    private OleDbConnection GetConnection()
    {
      // jeżeli dane składowe mają wartość null, to znaczy że
      // połączenie nie zostało utworzone ani otwarte
      if (_conn == null || _conn.State == ConnectionState.Closed)
      {
         // odczytanie ciągu połączenia do bazy danych, zmienić w razie potrzeby
         string connString = ConfigurationManager.ConnectionStrings["Books"].ConnectionString;

         try
         {
            // pobranie połączenia do bazy danych
            _conn = new OleDbConnection(connString);

            // otwarcie połączenia
            _conn.Open();
         }
         catch (Exception ex)
         {
            labMsg.Text = "[GetConnection] Wystąpił błąd w czasie dostępu do bazy danyych";
            labMsg.Text += "<br/>" + ex.Message;
            if (_conn != null)
               _conn.Close();
         }
      }
      return _conn;
    }
}
