// Copyright © Selmo Technology GmbH. All Rights Reserved

using Novus.Connectivity.Common;
using Novus.Connectivity.Service;
using SelmoStudio.Hmi.Server.Db.Context;
using System.Text;

namespace SelmoStudio.Hmi.Server.ProcessValue.Model
{
    public class HistoryValueGroupCollector
    {
        internal int CollectorNumber { get; }

        private readonly HistoryValueGroupSettings _settings;

        internal HistoryValueGroupCollector(HistoryValueGroupSettings settings, IProcessValueDbContext dbContext)
        {
            _settings = settings;
            CollectionRateInMs = (int)_settings.CollectingRate;
            CollectorNumber = _settings.GroupId;
        }

        public int CollectionRateInMs { get; }

        private int _currentHour = 0;

        internal void WriteValues(DateTimeOffset timestamp, ValueInfo valueInfo, IProcessValueDbContext dbContext)
        {
            var hour = timestamp.LocalDateTime.Hour;
            if (hour != _currentHour)
            {
                CreateNewTable(timestamp, dbContext);
            }

            WriteValuesToDb(timestamp, valueInfo, dbContext);
        }

        private void CreateNewTable(DateTimeOffset timestamp, IProcessValueDbContext dbContext)
        {
            var guidList = ToGuidList(_settings.ValueInfos);
            dbContext.ExecuteCreateHistoryTable(_settings.GroupId, guidList);
        }

        private void WriteValuesToDb(DateTimeOffset timestamp, ValueInfo valueInfo, IProcessValueDbContext dbContext)
        {
            var currentValues = GetCurrentValues(_settings.ValueInfos, valueInfo);
            var guidList = ToGuidList(_settings.ValueInfos);
            var insertDataAsString = GetValueDataInsertQueryPartAsString(currentValues);
            dbContext.ExecuteInsertData(_settings.GroupId, guidList, insertDataAsString);
        }

        private List<IProcessValue> GetCurrentValues(List<IProcessValueInfo> valueInfos, ValueInfo valueInfo)
        {
            List<IProcessValue> values = new();
            var valuelookup = valueInfo.ProcessValues;
            foreach (var pvi in valueInfos)
            {
                values.Add(valuelookup[pvi.Id]);
            }
            return values;
        }

        private List<Guid> ToGuidList(List<IProcessValueInfo> values)
        {
            List<Guid> guids = new List<Guid>();
            foreach (var pvInfo in values)
            {
                guids.Add(pvInfo.Id.Guid);
            }
            return guids;
        }

        private string GetValueDataInsertQueryPartAsString(List<IProcessValue> values)
        {
            char separator = ',';
            StringBuilder queryPart = new StringBuilder();

            foreach (var val in values)
            {
                queryPart.Append($"{val}{separator}");
            }

            var cleanQuery = queryPart.ToString().TrimEnd(separator);
            return cleanQuery;
        }
    }
}