public TimeLine BuildFullDayTimeLine(bool startup = false)
        {
            TimeLineMutex.WaitOne();

            //System.Threading.Thread.Sleep(30000);

            EnableIntervalSuspend = GlobalSettings.ApplicationSettings.EnableIntervalSuspend;
            EnableEveningSuspend = GlobalSettings.ApplicationSettings.EnableEveningSuspend;

            TimeSpan? dayStart = null;
            TimeSpan? dayEnd = null;
            TimeLineState eveningIdleState = TimeLineState.Idle;

            if (GlobalSettings.ApplicationSettings.EnableEveningSuspend)
            {
                dayStart = GlobalSettings.ApplicationSettings.ServiceStartTime;
                dayEnd = GlobalSettings.ApplicationSettings.ServiceStopTime;
                eveningIdleState = GetTimeLineState(GlobalSettings.ApplicationSettings.EveningSuspendType);
            }

            TimeLine timeLine = CreateBaseTimeLine(dayStart, dayEnd, eveningIdleState);

            if (GlobalSettings.ApplicationSettings.EnableIntervalSuspend)
            {
                TimeSpan? intervalStart = GlobalSettings.ApplicationSettings.IntervalStartTime;
                TimeSpan? intervalEnd = GlobalSettings.ApplicationSettings.IntervalStopTime;

                if (intervalStart == null)
                    intervalStart = dayStart;
                if (intervalEnd == null)
                    intervalEnd = dayEnd;

                if (intervalStart == null)
                    intervalStart = TimeSpan.FromMinutes(0);
                if (intervalEnd == null)
                    intervalEnd = TimeSpan.FromMinutes(MinutesInDay - 1);

                TimeSpan? wakeInterval = GlobalSettings.ApplicationSettings.ServiceWakeInterval;
                TimeSpan? suspendInterval = GlobalSettings.ApplicationSettings.ServiceSuspendInterval;

                if (wakeInterval != null)
                {
                    TimeLineMinute suspendMinute;
                    suspendMinute.State = GetTimeLineState(GlobalSettings.ApplicationSettings.ServiceSuspendType);
                    suspendMinute.Layer = TimeLineLayer.IntervalSuspend;
                    suspendMinute.Mandatory = false;

                    TimeLineMinute runningMinute;
                    runningMinute.State = TimeLineState.Running;
                    runningMinute.Mandatory = true;
                    runningMinute.Layer = TimeLineLayer.IntervalSuspend;

                    List<TimeLinePattern> patterns = new List<TimeLinePattern>();

                    TimeLinePattern wakePattern;
                    wakePattern.StartTime = TimeSpan.FromMinutes(0);
                    wakePattern.EndTime = wakeInterval.Value - TimeSpan.FromMinutes(1);
                    wakePattern.Minute = runningMinute;

                    patterns.Add(wakePattern);

                    if (suspendInterval != null)
                    {
                        TimeLinePattern suspendPattern;
                        suspendPattern.StartTime = wakePattern.EndTime + TimeSpan.FromMinutes(1);
                        suspendPattern.EndTime = wakePattern.EndTime + suspendInterval.Value;
                        suspendPattern.Minute = suspendMinute;
                        patterns.Add(suspendPattern);
                    }

                    timeLine = AddRepeatingPattern(timeLine, patterns, runningMinute, intervalStart.Value, intervalEnd.Value);
                    
                    if (GlobalSettings.ApplicationSettings.MeterHistoryTimeLineAdjust)
                    {
                        TimeLineMinute dontCareMinute;
                        dontCareMinute.State = TimeLineState.Unspecified;
                        dontCareMinute.Mandatory = false;
                        dontCareMinute.Layer = TimeLineLayer.MeterHistory;

                        TimeLineMinute meterMinute;
                        meterMinute.State = TimeLineState.Running;
                        meterMinute.Mandatory = true;
                        meterMinute.Layer = TimeLineLayer.MeterHistory;

                        int historyStartMinute = GlobalSettings.ApplicationSettings.MeterHistoryStartMinute == null ? -2 : GlobalSettings.ApplicationSettings.MeterHistoryStartMinute.Value;
                        int historyEndMinute = GlobalSettings.ApplicationSettings.MeterHistoryEndMinute == null ? 29 : GlobalSettings.ApplicationSettings.MeterHistoryEndMinute.Value;

                        patterns = new List<TimeLinePattern>();

                        TimeLinePattern dontCarePattern;
                        dontCarePattern.StartTime = TimeSpan.FromMinutes(0);
                        dontCarePattern.EndTime = TimeSpan.FromMinutes(60 + historyStartMinute - 1); // 2 hourhistory update cycle
                        dontCarePattern.Minute = dontCareMinute;
                        patterns.Add(dontCarePattern);

                        wakePattern.StartTime = TimeSpan.FromMinutes(60 + historyStartMinute);
                        wakePattern.EndTime = TimeSpan.FromMinutes(60 + historyEndMinute);
                        wakePattern.Minute = meterMinute;
                        patterns.Add(wakePattern);

                        dontCarePattern.StartTime = TimeSpan.FromMinutes(60 + historyEndMinute + 1);
                        dontCarePattern.EndTime = TimeSpan.FromMinutes(119); // 2 hourhistory update cycle
                        dontCarePattern.Minute = dontCareMinute;
                        patterns.Add(dontCarePattern);

                        timeLine = AddRepeatingPattern(timeLine, patterns, dontCareMinute, TimeSpan.FromMinutes(0), TimeSpan.FromMinutes(MinutesInDay - 1));
                    }
                }
            }

            FullDayTimeLine = timeLine;

            TimeLineMutex.ReleaseMutex();

            return timeLine;
        }
        private static TimeLine AddRepeatingPattern(TimeLine timeLineIn, List<TimeLinePattern> patterns, TimeLineMinute defaultMinute, TimeSpan startTime, TimeSpan endTime)
        {
            TimeLine timeLine = timeLineIn;
            if (patterns.Count == 0)
                return timeLine;
            timeLine.IsDefault = false;
            TimeLine pattern = BuildTimeLine(patterns, defaultMinute);

            int pos = (int)startTime.TotalMinutes;
            int endPos = (int)endTime.TotalMinutes;
            int patPos = 0;

            while (pos < endPos)
            {
                // do not overwrite mandatory state
                // do not use an Unspecified state
                if (!timeLine.Minute[pos].Mandatory && pattern.Minute[patPos].State != TimeLineState.Unspecified)
                    timeLine.Minute[pos++] = pattern.Minute[patPos++];
                else
                {
                    pos++;
                    patPos++;
                }
                if (patPos >= pattern.Minute.Length)
                    patPos = 0;
            }

            return timeLine;
        }