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

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

        public BTLPartController()
        {
        }

        #endregion Public Constructors

        #region Public Methods

        /// <summary>
        /// Conversion of base class to DB model class
        /// </summary>
        /// <param name="corePart"></param>
        /// <param name="currProjDbId"></param>
        /// <returns></returns>
        public BTLPartModel ConvertFromCore(Core.BTLPartM corePart, int currProjDbId)
        {
            BTLPartModel answ = new BTLPartModel();
            if (corePart != null)
            {
                answ = new BTLPartModel()
                {
                    PartId = corePart.nPartId,
                    PDN = corePart.nPDN,
                    DO = corePart.bDO,
                    NAM = corePart.sNAM,
                    W = corePart.dBtlW,
                    L = corePart.dBtlL,
                    H = corePart.dBtlH,
                    Material = corePart.sMATERIAL,
                    CNT = corePart.nCNT,
                    //TBP = corePart.nTBP,
                    //DON = corePart.nDON,
                    //ROT = corePart.nROT,
                    //GRP = corePart.sGRP,
                    //UNT = corePart.nUNT,
                    CALC_State = (int)corePart.nState,
                    ProjDbId = currProjDbId
                };
            }
            return answ;
        }

        /// <summary>
        /// Conversion of base class to DB model class
        /// </summary>
        /// <param name="corePart"></param>
        /// <returns></returns>
        public BTLPartModel Convert(Core.BTLPartM corePart)
        {
            BTLPartModel answ = new BTLPartModel();
            if (corePart != null)
            {
                answ = new BTLPartModel()
                {
                    PartId = corePart.nPartId,
                    PDN = corePart.nPDN,
                    DO = corePart.bDO,
                    NAM = corePart.sNAM,
                    W = corePart.dBtlW,
                    L = corePart.dBtlL,
                    H = corePart.dBtlH,
                    Material = corePart.sMATERIAL,
                    CNT = corePart.nCNT,
                    //TBP = corePart.nTBP,
                    //DON = corePart.nDON,
                    //ROT = corePart.nROT,
                    //GRP = corePart.sGRP,
                    //UNT = corePart.nUNT,
                    CALC_State = (int)corePart.nState
                };
            }
            return answ;
        }

        /// <summary>
        /// Create multiple BTLPart record associated to Project
        /// </summary>
        /// <param name="ProjID"></param>
        /// <param name="partData"></param>
        /// <returns></returns>
        public List<BTLPartModel> Create(int ProjID, List<BTLPartModel> partData)
        {
            // se è adv mode --> uso TUTTI i dati
            if (DbManager.AdvDataModel)
            {
                try
                {
                    using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
                    {
                        // Add to database
                        localDbCtx.BTLPartList.AddRange(partData);
                        // Commit changes
                        localDbCtx.SaveChanges();
                    }
                }
                catch (Exception exc)
                {
                    string errMessage = $"EXCEPTION on BTLPart.Create: {Environment.NewLine}{exc}";
                    Console.WriteLine(errMessage);
                    Log.Error(errMessage);
                }
                return partData;
            }
            // se non adv --> faccio solo copia degli id...
            else
            {
                List<int> partIdList = new List<int>();
                foreach (var item in partData)
                {
                    partIdList.Add(item.PartId);
                }
                return CreateBaseObj(ProjID, partIdList);
            }
        }

        /// <summary>
        /// Create multiple (empty) BTLPart record associated to Project
        /// </summary>
        /// <param name="ProjDbId"></param>
        /// <param name="rawListData"></param>
        /// <returns></returns>
        public List<BTLPartModel> CreateBaseObj(int ProjDbId, List<int> rawListData)
        {
            List<BTLPartModel> partData = new List<BTLPartModel>();

            foreach (var item in rawListData)
            {
                BTLPartModel newItem = new BTLPartModel() { ProjDbId = ProjDbId, PartId = item };
                partData.Add(newItem);
            }

            try
            {
                using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
                {
                    // Add to database
                    localDbCtx.BTLPartList.AddRange(partData);
                    // Commit changes
                    localDbCtx.SaveChanges();
                }
            }
            catch (Exception exc)
            {
                string errMessage = $"EXCEPTION on BTLPart.CreateBaseObj: {Environment.NewLine}{exc}";
                Console.WriteLine(errMessage);
                Log.Error(errMessage);
            }

            return partData;
        }

        /// <summary>
        /// Delete single BTLPart
        /// </summary>
        /// <param name="PartDbId"></param>
        /// <returns></returns>
        public bool Delete(int PartDbId)
        {
            bool done = false;
            using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
            {
                var item2del = localDbCtx
                .BTLPartList
                .Where(x => x.BTLPartDbId == PartDbId)
                .SingleOrDefault();
                try
                {
                    // Add to database
                    localDbCtx.BTLPartList.Remove(item2del);
                    // Commit changes
                    localDbCtx.SaveChanges();
                    done = true;
                }
                catch (Exception exc)
                {
                    string errMessage = $"EXCEPTION on BTLPart.Delete: {Environment.NewLine}{exc}";
                    Console.WriteLine(errMessage);
                    Log.Error(errMessage);
                }
            }
            return done;
        }

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

        public void Dispose()
        {
        }

        /// <summary>
        /// Get record by DBId
        /// </summary>
        /// <param name="PartDbId"></param>
        /// <returns></returns>
        public BTLPartModel FindByDbId(int PartDbId)
        {
            using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
            {
                return localDbCtx
                .BTLPartList
                .Where(x => x.BTLPartDbId == PartDbId)
                .SingleOrDefault();
            }
        }

        /// <summary>
        /// Get record by ExtId
        /// </summary>
        /// <param name="PartId"></param>
        /// <returns></returns>
        public BTLPartModel FindByPartId(int PartId)
        {
            using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
            {
                return localDbCtx
                .BTLPartList
                .Where(x => x.PartId == PartId)
                .SingleOrDefault();
            }
        }

        /// <summary>
        /// Get record by ProjDbId + PartId
        /// </summary>
        /// <param name="PartId"></param>
        /// <param name="ProjDbId"></param>
        /// <returns></returns>
        public BTLPartModel FindByPartIdProjDbId(int PartId, int ProjDbId)
        {
            using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
            {
                return localDbCtx
                .BTLPartList
                .Where(x => x.PartId == PartId && x.ProjDbId == ProjDbId)
                .FirstOrDefault();
            }
        }

        /// <summary>
        /// Get filtered data by ProjectId (ASC ordered)
        /// </summary>
        /// <param name="ProjDbId"></param>
        /// <returns></returns>
        public List<BTLPartModel> GetByProjectAsc(int ProjDbId)
        {
            using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
            {
                // retrieve
                return localDbCtx
                .BTLPartList
                .Where(x => x.ProjDbId == ProjDbId)
                .OrderBy(x => x.BTLPartDbId)
                .ToList();
            }
        }

        /// <summary>
        /// Get filtered data by ProjectId (DESC ordered)
        /// </summary>
        /// <param name="ProjDbId"></param>
        /// <returns></returns>
        public List<BTLPartModel> GetByProjectDesc(int ProjDbId)
        {
            using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
            {
                // retrieve
                return localDbCtx
                .BTLPartList
                .Where(x => x.ProjDbId == ProjDbId)
                .OrderByDescending(x => x.BTLPartDbId)
                .ToList();
            }
        }

        /// <summary>
        /// Get paginated data from DB (ASC ordered)
        /// </summary>
        /// <param name="PartDbIdStart"></param>
        /// <param name="numRecord"></param>
        /// <returns></returns>
        public List<BTLPartModel> GetPaginatedAsc(int PartDbIdStart, int numRecord)
        {
            List<BTLPartModel> answ = new List<BTLPartModel>();
            int numEnd = PartDbIdStart - numRecord;
            // check numEnd
            if (numEnd < 0)
                numEnd = 0;
            using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
            {
                // retrieve
                answ = localDbCtx
                        .BTLPartList
                        .Where(x => x.BTLPartDbId <= PartDbIdStart)
                        .OrderBy(x => x.BTLPartDbId)
                        .Take(numRecord)
                        .ToList();
            }
            return answ;
        }

        /// <summary>
        /// Get paginated data from DB (DESC ordered)
        /// </summary>
        /// <param name="PartDbIdStart"></param>
        /// <param name="numRecord"></param>
        /// <returns></returns>
        public List<BTLPartModel> GetPaginatedDesc(int PartDbIdStart, int numRecord)
        {
            List<BTLPartModel> answ = new List<BTLPartModel>();
            int numEnd = PartDbIdStart - numRecord;
            // check numEnd
            if (numEnd < 0)
                numEnd = 0;
            using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING))
            {
                // retrieve
                answ = localDbCtx
                        .BTLPartList
                        .Where(x => x.BTLPartDbId <= PartDbIdStart)
                        .OrderByDescending(x => x.BTLPartDbId)
                        .Take(numRecord)
                        .ToList();
            }
            return answ;
        }

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

                    //// update, vers 2
                    //localDbCtx.BTLPartList.Remove(item2del);
                    //localDbCtx.BTLPartList.Add(updItem);

                    // Commit changes
                    localDbCtx.SaveChanges();
                    done = true;
                }
                catch (Exception exc)
                {
                    string errMessage = $"EXCEPTION on BTLPart.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
    }
}