using EgtBEAMWALL.DataLayer.DatabaseModels;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;

namespace EgtBEAMWALL.DataLayer.Controllers
{
    public class LogMachineController : IDisposable
    {
        #region Public Constructors

        public LogMachineController()
        {
        }

        #endregion Public Constructors

        #region Public Methods

        /// <summary>
        /// Conversion of base class to DB model class
        /// </summary>
        /// <param name="coreMacLog"></param>
        /// <returns></returns>
        public LogMachineModel ConvertFromCore(Core.MachLog coreMacLog)
        {
            LogMachineModel answ = new LogMachineModel();
            if (coreMacLog != null)
            {
                answ = new LogMachineModel()
                {
                    AlarmCode = coreMacLog.AlarmCode,
                    AlarmDatetime = coreMacLog.AlarmDateTime,
                    AlarmMessage = coreMacLog.AlarmMessage,
                    AlarmOperation = coreMacLog.AlarmOperation,
                    AlarmType = coreMacLog.AlarmType,
                    CommandExecutedCorrectly = coreMacLog.CommandExecutedCorrectly,
                    CommandState = coreMacLog.CommandState,
                    CommandType = coreMacLog.CommandType,
                    Description = coreMacLog.Description,
                    NewOpState = coreMacLog.newOpState,
                    ResultType = coreMacLog.ResultType,
                    VarAddress = coreMacLog.VarAddress,
                    VarValue = coreMacLog.VarValue
                };
            }
            return answ;
        }

        /// <summary>
        /// Conversion from DB to Core class
        /// </summary>
        /// <param name="dbLog"></param>
        /// <returns></returns>
        public Core.MachLog ConvertToCore(LogMachineModel dbLog)
        {
            var newRecord = Core.MachLog.CreateMachLog(dbLog.AlarmCode, dbLog.AlarmDatetime, dbLog.AlarmMessage, dbLog.AlarmOperation, dbLog.AlarmType, dbLog.CommandExecutedCorrectly, dbLog.CommandState, dbLog.CommandType, dbLog.Description, dbLog.NewOpState, dbLog.ResultType, dbLog.VarAddress, dbLog.VarValue);
            return newRecord;
        }

        /// <summary>
        /// Create machine LOG record
        /// </summary>
        /// <param name="newLogMac"></param>
        /// <returns></returns>
        public bool Create(LogMachineModel newLogMac)
        {
            bool fatto = false;
            try
            {
                try
                {
                    using (var locallocalDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
                    {
                        // Add to database
                        locallocalDbCtx.LogMachineList.Add(newLogMac);
                        // Commit changes
                        locallocalDbCtx.SaveChanges();
                    }
                }
                catch (Exception exc)
                {
                    string errMessage = $"EXCEPTION on LogMachine.Create: {Environment.NewLine}{exc}";
                    Console.WriteLine(errMessage);
                    Log.Error(errMessage);
                }
            }
            catch
            { }
            return fatto;
        }

        /// <summary>
        /// Create machine LOG record (da modello dati CORE)
        /// </summary>
        /// <param name="newLogMac"></param>
        /// <returns></returns>
        public bool Create(Core.MachLog newMachLog)
        {
            var dbLogModel = ConvertFromCore(newMachLog);
            return Create(dbLogModel);
        }

        /// <summary>
        /// Delete by key
        /// </summary>
        /// <param name="LogDbId"></param>
        /// <returns></returns>
        public bool DeleteByKey(int LogDbId)
        {
            bool done = false;
            using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
            {
                var items2del = localDbCtx
                .LogMachineList
                .Where(x => x.LogDbId == LogDbId);
                try
                {
                    // Add to database
                    localDbCtx.LogMachineList.RemoveRange(items2del);
                    // Commit changes
                    localDbCtx.SaveChanges();
                    done = true;
                }
                catch (Exception exc)
                {
                    string errMessage = $"EXCEPTION on LogMachine.DeleteByKey: {Environment.NewLine}{exc}";
                    Console.WriteLine(errMessage);
                    Log.Error(errMessage);
                }
            }
            return done;
        }

        public void Dispose()
        {
        }

        /// <summary>
        /// Get record by LogDbId
        /// </summary>
        /// <param name="LogDbId"></param>
        /// <returns></returns>
        public LogMachineModel FindByDbId(int LogDbId)
        {
            using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
            {
                return localDbCtx
                .LogMachineList
                .Where(x => x.LogDbId == LogDbId)
                .SingleOrDefault();
            }
        }

        /// <summary>
        /// Get paginated data from DB (ASC ordered)
        /// </summary>
        /// <param name="dtStart"></param>
        /// <param name="dtEnd"></param>
        /// <returns></returns>
        public List<LogMachineModel> GetAsc(DateTime dtStart, DateTime dtEnd)
        {
            using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
            {
                // retrieve
                return localDbCtx
                .LogMachineList
                .Where(x => x.AlarmDatetime >= dtStart && x.AlarmDatetime <= dtEnd)
                .OrderBy(x => x.AlarmDatetime)
                .ToList();
            }
        }

        /// <summary>
        /// Get paginated data from DB (ASC ordered) in "core format"
        /// </summary>
        /// <param name="dtStart"></param>
        /// <param name="dtEnd"></param>
        /// <returns></returns>
        public List<Core.MachLog> GetCoreAsc(DateTime dtStart, DateTime dtEnd)
        {
            var rawData = GetAsc(dtStart, dtEnd);
            var coreData = rawData.Select(x => ConvertToCore(x)).ToList();
            return coreData;
        }

        /// <summary>
        /// Get paginated data from DB (DESC ordered) in "core format"
        /// </summary>
        /// <param name="dtStart"></param>
        /// <param name="dtEnd"></param>
        /// <returns></returns>
        public List<Core.MachLog> GetCoreDesc(DateTime dtStart, DateTime dtEnd)
        {
            var rawData = GetDesc(dtStart, dtEnd);
            var coreData = rawData.Select(x => ConvertToCore(x)).ToList();
            return coreData;
        }

        /// <summary>
        /// Get paginated data from DB (DESC ordered)
        /// </summary>
        /// <param name="dtStart"></param>
        /// <param name="dtEnd"></param>
        /// <returns></returns>
        public List<LogMachineModel> GetDesc(DateTime dtStart, DateTime dtEnd)
        {
            using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
            {
                // retrieve
                return localDbCtx
                .LogMachineList
                .Where(x => x.AlarmDatetime >= dtStart && x.AlarmDatetime <= dtEnd)
                .OrderByDescending(x => x.AlarmDatetime)
                .ToList();
            }
        }

        /// <summary>
        /// Update single LogMachineModel
        /// </summary>
        /// <param name="updItem"></param>
        /// <returns></returns>
        public bool Update(LogMachineModel updItem)
        {
            bool done = false;
            using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
            {
                var item2update = localDbCtx
                .LogMachineList
                .Where(x => x.LogDbId == updItem.LogDbId)
                .SingleOrDefault();
                try
                {
                    // update, vers 1...
                    localDbCtx.Entry(item2update).CurrentValues.SetValues(updItem);

                    // Commit changes
                    localDbCtx.SaveChanges();
                    done = true;
                }
                catch (Exception exc)
                {
                    string errMessage = $"EXCEPTION on LogMachine.Update: {Environment.NewLine}{exc}";
                    Console.WriteLine(errMessage);
                    Log.Error(errMessage);
                }
            }
            return done;
        }

        #endregion Public Methods

        #region Private Fields

        /// <summary>
        /// Istanza logger
        /// </summary>
        private NLog.Logger Log = LogManager.GetCurrentClassLogger();

        #endregion Private Fields
    }
}