using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


using Maser.Feanor.Model;
using System.Data.SqlClient;



namespace Maser.Feanor.Biz
{
    public class Results
    {
        public Result GetByPK(Int32 PK)
        {
            string query = String.Format("Select * from Results where PK = {0}", PK);
            try
            {
                return GetByQuery(query);
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public List<Result> GetByProject(Project project)
        {
            List<SqlParameter> parameters = new List<SqlParameter>();
            parameters.Add(new SqlParameter("@Project_PK", project.PK));
            try
            {
                List<Result> results = GetFromStoredProc("Results_GetByProject", parameters);
                return results;
            }
            catch (Exception e)
            {
                throw e;
            }
        }



        public List<Result> GetByProjectWindow(Int32 Project_PK, Int32 Sensor_PK)
        {
            List<SqlParameter> parameters = new List<SqlParameter>();
            parameters.Add(new SqlParameter("@ProjectPK", Project_PK));
            parameters.Add(new SqlParameter("@SensorPK", Sensor_PK));
            try
            {
                List<Result> results = GetFromStoredProc("Results_GetByProjectWindow", parameters);                
                return results;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public List<Result> GetByProjectWindowOudeHal(Int32 Project_PK, Int32 Sensor_PK)
        {
            List<SqlParameter> parameters = new List<SqlParameter>();
            parameters.Add(new SqlParameter("@ProjectPK", Project_PK));
            parameters.Add(new SqlParameter("@SensorPK", Sensor_PK));
            try
            {
                List<Result> results = GetFromStoredProc("ResultsOudeHal_GetByProjectWindow", parameters);
                return results;
            }
            catch (Exception e)
            {
                throw e;
            }
        }



        public Result GetLastBySensorPK(Int32 sensorPK)
        {
            return GetLastBySensorPK(sensorPK, false);
        }

      



        public Result GetLastBySensorPK(Int32 sensorPK, bool LimitedSearch)
        {
            List<SqlParameter> parameters = new List<SqlParameter>();
            parameters.Add(new SqlParameter("@PK", sensorPK));
            parameters.Add(new SqlParameter("@LimitedSearch", LimitedSearch ? 1 : 0));
            try
            {                
                List<Result> results = GetFromStoredProc("Results_GetLatestBySensorPK", parameters); 
                
                if (results.Count == 0)
                    return null;
                return results[0];  
            }
            catch (Exception e)
            {
                Console.WriteLine("GetLastBySensorPK Error: "+ e);
                throw e;
            }
        }



        public bool Exists(Result result)
        {
            try
            {
                return (GetByPK(result.PK) != null);
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public void Add(List<Result> results)
        {
            SqlConnection myConnection = new SqlConnection(Properties.Settings.Default.FeanorConnStr);

            try
            {
                myConnection.Open();
                foreach (Result result in results)
                {                  

                    SqlCommand cmd = new SqlCommand(@"INSERT INTO Results (SensorPK, Value, Timestamp, CalibrationPK) VALUES (@sensorpk, @value, @timestamp, @calibrationpk)", myConnection);
                    {                       

                        cmd.Parameters.AddWithValue("@sensorpk", result.SensorPK);
                        cmd.Parameters.AddWithValue("@value", result.Value);
                        cmd.Parameters.AddWithValue("@timestamp", result.TimeStamp.FormatSQL());
                        cmd.Parameters.AddWithValue("@calibrationpk", result.CalibrationPK);
                    }                   

                    cmd.ExecuteNonQuery();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                myConnection.Close();
            }
        }

        public void AddOudeHal(List<Result> results)
        {
            SqlConnection myConnection = new SqlConnection(Properties.Settings.Default.FeanorConnStr);

            try
            {
                myConnection.Open();
                foreach (Result result in results)
                {                   
                    SqlCommand cmd = new SqlCommand(@"INSERT INTO ResultsOudeHal (SensorPK, Value, Timestamp, CalibrationPK) VALUES (@sensorpk, @value, @timestamp, @calibrationpk)", myConnection);
                    {

                        cmd.Parameters.AddWithValue("@sensorpk", result.SensorPK);
                        cmd.Parameters.AddWithValue("@value", result.Value);
                        cmd.Parameters.AddWithValue("@timestamp", result.TimeStamp.FormatSQL());
                        cmd.Parameters.AddWithValue("@calibrationpk", result.CalibrationPK);
                    }

                    cmd.ExecuteNonQuery();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                myConnection.Close();
            }
        }



        private Result GetByQuery(string query)
        {
            Result result = null;
            SqlConnection myConnection = new SqlConnection(Properties.Settings.Default.FeanorConnStr);
            SqlDataReader myReader = null;
            try
            {
                myConnection.Open();

                SqlCommand myCommand = new SqlCommand(query, myConnection);
                myReader = myCommand.ExecuteReader();
                if (myReader.HasRows)
                {
                    myReader.Read();
                    result = new Result(myReader.GetInt32(0), myReader.GetInt32(1),(double)myReader.GetFloat(2), myReader.GetDateTime(3), myReader.GetInt32(4));
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                myReader.Close();
                myConnection.Close(); // Martijn
                /* 
                https://msdn.microsoft.com/en-us/library/haa3afyz(v=vs.110).aspx
                Do not call Close or Dispose on a Connection, a DataReader, or any other managed object in the Finalize method of your class. 
                In a finalizer, only release unmanaged resources that your class owns directly. 
                If your class does not own any unmanaged resources, do not include a Finalize method in your class definition. 
                For more information, see Garbage Collection.
                */
            }
            return result;
        }


        private List<Result> GetListByQuery(string query)
        {
            List<Result> result = new List<Result>();
            SqlConnection myConnection = new SqlConnection(Properties.Settings.Default.FeanorConnStr);
            SqlDataReader myReader = null;

            try
            {
                myConnection.Open();

                SqlCommand myCommand = new SqlCommand(query, myConnection);
                myReader = myCommand.ExecuteReader();
                if (myReader.HasRows)
                {
                    while (myReader.Read())
                    {
                        result.Add(new Result(myReader.GetInt32(0), myReader.GetInt32(1), (double)myReader.GetFloat(2), myReader.GetDateTime(3), myReader.GetInt32(4)));
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                myReader.Close();
                /* 
                https://msdn.microsoft.com/en-us/library/haa3afyz(v=vs.110).aspx
                Do not call Close or Dispose on a Connection, a DataReader, or any other managed object in the Finalize method of your class. 
                In a finalizer, only release unmanaged resources that your class owns directly. 
                If your class does not own any unmanaged resources, do not include a Finalize method in your class definition. 
                For more information, see Garbage Collection.
                */
            }
            return result;
        }


        private List<Result> GetFromStoredProc(string procedure, List<SqlParameter> parameters)
        {           
            List<Result> result = new List<Result>();
            SqlConnection myConnection = new SqlConnection(Properties.Settings.Default.FeanorConnStr);
            SqlDataReader myReader = null;

            try
            {
                SqlCommand myCommand = new SqlCommand(procedure, myConnection);
                               
                foreach (SqlParameter p in parameters)
                {                   
                    myCommand.Parameters.Add(p);
                }
                
                myCommand.CommandType = System.Data.CommandType.StoredProcedure;
                myConnection.Open();
                myReader = myCommand.ExecuteReader();
                 
               if (myReader.HasRows)
               {
                    while (myReader.Read())
                    {                            
                        result.Add(new Result(myReader.GetInt32(0), myReader.GetInt32(1), (double)myReader.GetFloat(2), myReader.GetDateTime(3), myReader.GetInt32(4)));                                         
                    }
                }
                
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                throw e;
            }
            finally
            {     
              
                myReader.Close(); // was er origineel wel              
                    
               myConnection.Close(); // was er origineel niet
            }
            return result;
        }


    }
}
