/// <summary>
        /// Must make sure the input tracings are continuous in time e.g. no overlaps or gaps
        /// </summary>
        /// <param name="inData"></param>
        /// <param name="FHRsList"></param>
        /// <param name="UPsList"></param>
        private bool UpdateEndTracingTime(TracingData inData, List <byte> FHRsList, List <byte> UPsList)
        {
            lock (s_mainLockObject)
            {
                String logHeader = "Patterns Add On Manager, Patterns Session Data, Update End Tracing Time";
                int    nTimeDiff = (int)(inData.StartTime - EndTimeOfPreviousTracings).TotalSeconds;
                if (nTimeDiff < 1) // Overlap
                {
                    int toRem = Math.Abs(nTimeDiff) + 1;
                    Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, "Overlap (sec): " + toRem.ToString());
                    UPsList.RemoveRange(0, toRem);
                    FHRsList.RemoveRange(0, toRem * 4);
                }
                else if (nTimeDiff > 1) // Gap
                {
                    if (nTimeDiff > MaximumBridgeableGap)
                    {
                        Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, "The gap is too long, engine restarting.");
                        return(false);
                    }

                    Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, "Gap (sec): " + nTimeDiff.ToString());
                    for (int toAdd = nTimeDiff - 1; toAdd > 0; toAdd--)
                    {
                        UPsList.Insert(0, NoData);
                        FHRsList.InsertRange(0, new byte[] { NoData, NoData, NoData, NoData });
                    }
                }

                EndTimeOfPreviousTracings = EndTimeOfPreviousTracings.AddSeconds(UPsList.Count);
                Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, "EndTimeOfPreviousTracings: " + EndTimeOfPreviousTracings.ToString());
                return(true);
            }
        }
        private void ReInstance(TracingData inData, int nTracingLength)
        {
            lock (s_mainLockObject)
            {
                UnInitSessionData();
                LastRequest = DateTime.Now;

                // Clear buffers of live calculation
                m_fhrToProcess.Clear();
                m_upToProcess.Clear();

                String logHeader = "Patterns Add On Manager, Patterns Session Data, ReInstance";
                Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, "Engine should be null, is " + Engine == null ? "null" : "exists");
                Engine = new PatternsProcessorWrapper(GUID, DateTime.Now);
                Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, "Engine should exist, is " + Engine == null ? "null" : "exists");
                System.Diagnostics.Trace.WriteLine("ReInstance: inData.StartTime (before RI)= " + StartTime.ToString());
                StartTime = inData.StartTime;
                EndTimeOfPreviousTracings = inData.StartTime.AddSeconds(nTracingLength);
                System.Diagnostics.Trace.WriteLine("PrepareProcessPatterns: EndTimeOfPreviousTracings (after RI)= " + EndTimeOfPreviousTracings.ToString());
                System.Diagnostics.Trace.WriteLine("PrepareProcessPatterns: inData.StartTime (after RI)= " + StartTime.ToString());
                Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, "Engine recreated");
            }
        }
        /// <summary>
        /// High level method called by WCF module, while requesting patterns calculation.
        /// </summary>
        /// <param name="inData">Contains the current chunk of tracings data</param>
        /// <returns></returns>
        public void PrepareProcessPatterns()
        {
            String logHeader = "Patterns Add On Manager, Patterns Session Data, Process Patterns";

            System.Diagnostics.Trace.WriteLine("PrepareProcessPatterns reached, GUIDQueue size: " + m_GUIDQueue.Count);
            if (m_GUIDQueue.Count <= 0)
            {
                Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, "No requests in queue, waiting for new requests.");
                System.Diagnostics.Trace.WriteLine("PrepareProcessPatterns: m_GUIDQueue size <= 0");
                return;
            }

            System.Diagnostics.Trace.WriteLine("PrepareProcessPatterns: (before TryPeek) GUIDQueue size: " + m_GUIDQueue.Count);
            TracingData inData;
            bool        bSucc = m_GUIDQueue.TryPeek(out inData);

            if (!bSucc || inData == null)
            {
                System.Diagnostics.Trace.WriteLine("Couldn't retrieve TracingData, probably broken GUID, try reinitializing.");
                Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, "Couldn't retrieve TracingData, probably broken GUID, try reinitializing.");
                return;
            }

            System.Diagnostics.Trace.WriteLine("PrepareProcessPatterns: GUIDQueue size: " + m_GUIDQueue.Count);
            String inDataTrace = "PreviousDetectededEndTime = " + inData.PreviousDetectededEndTime + "\nStartTime = " + inData.StartTime;

            Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, inDataTrace);
            Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, "GUIDQueue size: " + m_GUIDQueue.Count);

            //Remove calculated data
            CleanSessionData(inData.PreviousDetectededEndTime);

            // Do it only once in the beginning, otherwise causes time slides in results (see GEII-2)
            if (StartTime == DateTime.MinValue)
            {
                StartTime = inData.StartTime;
            }

            LastRequest = DateTime.Now;
            List <byte> FHRsList = Convert.FromBase64String(inData.Fhr).ToList();
            List <byte> UPsList  = Convert.FromBase64String(inData.Up).ToList();

            if (UPsList.Count * 4 != FHRsList.Count)
            {
                EqualizeData(UPsList, FHRsList);
            }

            bool bBridgeableGap = true;

            if (EndTimeOfPreviousTracings == DateTime.MinValue)
            {
                EndTimeOfPreviousTracings = inData.StartTime.AddSeconds(UPsList.Count - 1);
            }
            else
            {
                bBridgeableGap = UpdateEndTracingTime(inData, FHRsList, UPsList);
            }

            System.Diagnostics.Trace.WriteLine("PrepareProcessPatterns: EndTimeOfPreviousTracings = " + EndTimeOfPreviousTracings.ToString());
            System.Diagnostics.Trace.WriteLine("PrepareProcessPatterns: inData.StartTime = " + inData.StartTime.ToString());

            if (!bBridgeableGap)
            {
                Logger.WriteLogEntry(TraceEventType.Error, logHeader, "Reinstance Engine");
                System.Diagnostics.Trace.WriteLine("PrepareProcessPatterns: Reinstance");
                ReInstance(inData, UPsList.Count);
            }

            int nExistingTracingsLength = m_upToProcess.Count;

            m_fhrToProcess.AddRange(FHRsList);
            m_upToProcess.AddRange(UPsList);

            if (m_upToProcess.Count >= MinimumTracingsLength)
            {
                //bool blive = (m_upToProcess.Count < 900 || (m_upToProcess.Count < 1800 && CalcTime30Sec < 1000));
                var FHRs = m_fhrToProcess.ToArray();
                var UPs  = m_upToProcess.ToArray();

                DateTime curStartTime = inData.StartTime.AddSeconds(-nExistingTracingsLength);
                String   msg          = "Tracing Start Time: " + curStartTime.ToString() +
                                        "\nAbsolute Start Time: " + StartTime.ToString() +
                                        "\nTracing Length: " + UPs.Length.ToString();

                //if (UPs.Length < 900)
                //{
                Task.Factory.StartNew(() =>
                {
                    Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, "Processing live");
                    Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, msg);
                    ProcessPatterns(UPs, FHRs, true);
                });
                //}
                //else if (UPs.Length > 1800)
                //{
                //    Task.Factory.StartNew(() =>
                //    {
                //        Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, "Processing retrospective");
                //        Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, msg);
                //        RetrospectiveQueue.Queue.AddToQueue(this, UPs, FHRs);
                //    });
                //}
                //else
                //{
                //    if (CalcTime30Sec > 1000)
                //    {
                //        Task.Factory.StartNew(() =>
                //        {
                //            Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, "Processing retrospective by load calculation");
                //            Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, msg);
                //            RetrospectiveQueue.Queue.AddToQueue(this, UPs, FHRs);
                //        });
                //    }
                //    else
                //    {
                //        Task.Factory.StartNew(() =>
                //        {
                //            Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, "Processing live by load calculation");
                //            Logger.WriteLogEntry(TraceEventType.Verbose, logHeader, msg);
                //            ProcessPatterns(UPs, FHRs, blive);
                //        });
                //    }
                //}
            }
            else
            {
                TracingData td;
                bool        bSuccess = m_GUIDQueue.TryDequeue(out td);
                Task.Factory.StartNew(() => PrepareProcessPatterns());
            }
        }