public UserActivityTracker(
            IActivityRecordsRepository activityRecordsRepository,
            IActivitiesRepository activitiesRepository,
            IActivityTrackingSettings settings,
            IUserInputTracker inputTracker)
        {
            _activityRecordsRepository = activityRecordsRepository;
            _settings = settings;
            _inputTracker = inputTracker;

            List<Activity> activities = activitiesRepository.GetActivities().ToList();
            _defaultActivity = activities[0];
            _breakActivity = activities[1];
            _homeActivity = activities[5];
        }
        /// <summary>
        /// Creates an instance of <see cref="T:Caliburn.Micro.PropertyChangedBase"/>.
        /// </summary>
        public ActivityRecordsLogChartPiece(
            Activity activity,
            IEnumerable<ActivityRecord> records,
            TimeSpan workdayDuration)
        {
            _activity = activity;
            Records = records.ToList();

            if (Records == null || !Records.Any())
            {
                return;
            }

            TotalDuration = (int)Math.Round(TimeSpan.FromTicks(Records.Sum(r => r.DurationTicks)).TotalMinutes);

            var totalWorkdayMinutes = (int)Math.Round(workdayDuration.TotalMinutes);

            if (totalWorkdayMinutes == 0)
            {
                return;
            }

            WorkdayPercent = (int)(TotalDuration / (totalWorkdayMinutes / 100d));
        }
        private static void LogUserActivity(
            IActivityRecordsRepository activityRecordsRepository,
            Action<ActivityRecord> setIdleRecordActivity,
            Activity defaultActivity,
            DateTime userInputStartTime,
            DateTime lastUserInputTime,
            DateTime currentTime,
            IActivityTrackingSettings settings,
            Action onActivityLogUpdated,
            Action<ActivityRecord> onUnknownActivityLogged)
        {
            var activeTime = lastUserInputTime - userInputStartTime;
            var idleTime = currentTime - lastUserInputTime;

            bool logUpdated = false;

            Action<ActivityRecord, Action<ActivityRecord>> addOrUpdateRecord = (record, addOrUpdate) =>
            {
                if (record.Idle)
                {
                    setIdleRecordActivity(record);
                }

                addOrUpdate(record);

                if (record.Idle && record.Activity == null)
                {
                    onUnknownActivityLogged(record);
                }

                logUpdated = true;
            };

            Action<ActivityRecord> addRecord = record => addOrUpdateRecord(record, activityRecordsRepository.Add);
            Action<ActivityRecord> updateRecord = record => addOrUpdateRecord(record, activityRecordsRepository.Update);

            try
            {
                ActivityRecord lastRecord = activityRecordsRepository.GetLastRecord();

                if (lastRecord != null)
                {
                    TimeSpan idleTimeAfterLastRecord = userInputStartTime - lastRecord.EndTime;

                    if (lastRecord.Idle)
                    {
                        // Cannot log this yet. Not enough data.
                        if (activeTime < settings.MinimumActivityDuration && idleTime < settings.MinimumIdleDuration)
                        {
                            return;
                        }

                        if (activeTime < settings.MinimumActivityDuration)
                        {
                            lastRecord.EndTime = currentTime;
                            updateRecord(lastRecord);

                            return;
                        }

                        if (idleTimeAfterLastRecord.TotalMilliseconds > 0)
                        {
                            lastRecord.EndTime = userInputStartTime;
                            updateRecord(lastRecord);
                        }
                    }
                    else
                    {
                        if (idleTimeAfterLastRecord >= settings.MinimumIdleDuration)
                        {
                            var newIdleRecord = new ActivityRecord
                            {
                                StartTime = lastRecord.EndTime,
                                EndTime = userInputStartTime,
                                Idle = true,
                            };

                            addRecord(newIdleRecord);
                        }
                        else
                        {
                            lastRecord.EndTime = lastUserInputTime;
                            updateRecord(lastRecord);
                            activeTime = TimeSpan.Zero;
                        }
                    }
                }

                if (activeTime < settings.MinimumActivityDuration && idleTime < settings.MinimumIdleDuration)
                {
                    return;
                }

                if (activeTime >= settings.MinimumActivityDuration)
                {
                    addRecord(
                        new ActivityRecord
                        {
                            StartTime = userInputStartTime,
                            EndTime = lastUserInputTime,
                            Idle = false,
                            Activity = defaultActivity
                        });
                }
                else if (activeTime != TimeSpan.Zero)
                {
                    idleTime += activeTime;
                    lastUserInputTime = userInputStartTime;
                }

                if (idleTime < settings.MinimumIdleDuration)
                {
                    return;
                }

                var idleRecord = new ActivityRecord
                {
                    StartTime = lastUserInputTime,
                    EndTime = currentTime,
                    Idle = true,
                    Activity = defaultActivity
                };

                addRecord(idleRecord);
            }
            finally
            {
                if (logUpdated)
                {
                    onActivityLogUpdated();
                }
            }
        }