public ScheduleCleanUpStateTests()
 {
     state = new ScheduleCleanUpState(queue);
 }
        private static void configurePullTransitions(
            ITransitionConfigurator transitions,
            ITogglDatabase database,
            ITogglApi api,
            ITogglDataSource dataSource,
            ITimeService timeService,
            IAnalyticsService analyticsService,
            IScheduler scheduler,
            StateResult entryPoint,
            ILeakyBucket leakyBucket,
            IRateLimiter rateLimiter,
            ISyncStateQueue queue)
        {
            var delayState = new WaitForAWhileState(scheduler, analyticsService);

            var fetchAllSince = new FetchAllSinceState(api, database.SinceParameters, timeService, leakyBucket, rateLimiter);

            var ensureFetchWorkspacesSucceeded        = new EnsureFetchListSucceededState <IWorkspace>();
            var ensureFetchWorkspaceFeaturesSucceeded = new EnsureFetchListSucceededState <IWorkspaceFeatureCollection>();
            var ensureFetchTagsSucceeded        = new EnsureFetchListSucceededState <ITag>();
            var ensureFetchClientsSucceeded     = new EnsureFetchListSucceededState <IClient>();
            var ensureFetchProjectsSucceeded    = new EnsureFetchListSucceededState <IProject>();
            var ensureFetchTasksSucceeded       = new EnsureFetchListSucceededState <ITask>();
            var ensureFetchTimeEntriesSucceeded = new EnsureFetchListSucceededState <ITimeEntry>();
            var ensureFetchUserSucceeded        = new EnsureFetchSingletonSucceededState <IUser>();
            var ensureFetchPreferencesSucceeded = new EnsureFetchSingletonSucceededState <IPreferences>();

            var scheduleCleanUp = new ScheduleCleanUpState(queue);

            var detectGainingAccessToWorkspaces =
                new DetectGainingAccessToWorkspacesState(
                    dataSource.Workspaces,
                    analyticsService,
                    () => new HasFinsihedSyncBeforeInteractor(dataSource));

            var resetSinceParams = new ResetSinceParamsState(database.SinceParameters);

            var persistNewWorkspaces =
                new PersistNewWorkspacesState(dataSource.Workspaces);

            var detectLosingAccessToWorkspaces =
                new DetectLosingAccessToWorkspacesState(dataSource.Workspaces, analyticsService);

            var deleteRunningInaccessibleTimeEntry = new DeleteInaccessibleRunningTimeEntryState(dataSource.TimeEntries);

            var markWorkspacesAsInaccessible = new MarkWorkspacesAsInaccessibleState(dataSource.Workspaces);

            var persistWorkspaces =
                new PersistListState <IWorkspace, IDatabaseWorkspace, IThreadSafeWorkspace>(dataSource.Workspaces, Workspace.Clean);

            var updateWorkspacesSinceDate =
                new UpdateSinceDateState <IWorkspace>(database.SinceParameters);

            var detectNoWorkspaceState = new DetectNotHavingAccessToAnyWorkspaceState(dataSource);

            var persistWorkspaceFeatures =
                new PersistListState <IWorkspaceFeatureCollection, IDatabaseWorkspaceFeatureCollection, IThreadSafeWorkspaceFeatureCollection>(
                    dataSource.WorkspaceFeatures, WorkspaceFeatureCollection.From);

            var persistUser =
                new PersistSingletonState <IUser, IDatabaseUser, IThreadSafeUser>(dataSource.User, User.Clean);

            var noDefaultWorkspaceDetectingState = new DetectUserHavingNoDefaultWorkspaceSetState(dataSource, analyticsService);

            var trySetDefaultWorkspaceState = new TrySetDefaultWorkspaceState(timeService, dataSource);

            var persistTags =
                new PersistListState <ITag, IDatabaseTag, IThreadSafeTag>(dataSource.Tags, Tag.Clean);

            var updateTagsSinceDate = new UpdateSinceDateState <ITag>(database.SinceParameters);

            var persistClients =
                new PersistListState <IClient, IDatabaseClient, IThreadSafeClient>(dataSource.Clients, Client.Clean);

            var updateClientsSinceDate = new UpdateSinceDateState <IClient>(database.SinceParameters);

            var persistPreferences =
                new PersistSingletonState <IPreferences, IDatabasePreferences, IThreadSafePreferences>(dataSource.Preferences, Preferences.Clean);

            var persistProjects =
                new PersistListState <IProject, IDatabaseProject, IThreadSafeProject>(dataSource.Projects, Project.Clean);

            var updateProjectsSinceDate = new UpdateSinceDateState <IProject>(database.SinceParameters);

            var createProjectPlaceholders = new CreateArchivedProjectPlaceholdersState(dataSource.Projects, analyticsService);

            var persistTimeEntries =
                new PersistListState <ITimeEntry, IDatabaseTimeEntry, IThreadSafeTimeEntry>(dataSource.TimeEntries, TimeEntry.Clean);

            var updateTimeEntriesSinceDate = new UpdateSinceDateState <ITimeEntry>(database.SinceParameters);

            var persistTasks =
                new PersistListState <ITask, IDatabaseTask, IThreadSafeTask>(dataSource.Tasks, Task.Clean);

            var updateTasksSinceDate = new UpdateSinceDateState <ITask>(database.SinceParameters);

            var refetchInaccessibleProjects =
                new TryFetchInaccessibleProjectsState(dataSource.Projects, timeService, api.Projects);

            // start all the API requests first
            transitions.ConfigureTransition(entryPoint, fetchAllSince);

            // prevent overloading server with too many requests
            transitions.ConfigureTransition(fetchAllSince.PreventOverloadingServer, delayState);

            // detect gaining access to workspaces
            transitions.ConfigureTransition(fetchAllSince.Done, ensureFetchWorkspacesSucceeded);
            transitions.ConfigureTransition(ensureFetchWorkspacesSucceeded.Done, detectGainingAccessToWorkspaces);
            transitions.ConfigureTransition(detectGainingAccessToWorkspaces.Done, detectLosingAccessToWorkspaces);
            transitions.ConfigureTransition(detectGainingAccessToWorkspaces.NewWorkspacesDetected, resetSinceParams);
            transitions.ConfigureTransition(resetSinceParams.Done, persistNewWorkspaces);
            transitions.ConfigureTransition(persistNewWorkspaces.Done, fetchAllSince);

            // detect losing access to workspaces
            transitions.ConfigureTransition(detectLosingAccessToWorkspaces.Done, persistWorkspaces);
            transitions.ConfigureTransition(detectLosingAccessToWorkspaces.WorkspaceAccessLost, markWorkspacesAsInaccessible);
            transitions.ConfigureTransition(markWorkspacesAsInaccessible.Done, scheduleCleanUp);
            transitions.ConfigureTransition(scheduleCleanUp.Done, deleteRunningInaccessibleTimeEntry);
            transitions.ConfigureTransition(deleteRunningInaccessibleTimeEntry.Done, persistWorkspaces);

            // persist all the data pulled from the server
            transitions.ConfigureTransition(persistWorkspaces.Done, updateWorkspacesSinceDate);
            transitions.ConfigureTransition(updateWorkspacesSinceDate.Done, detectNoWorkspaceState);
            transitions.ConfigureTransition(detectNoWorkspaceState.Done, ensureFetchUserSucceeded);

            transitions.ConfigureTransition(ensureFetchUserSucceeded.Done, persistUser);
            transitions.ConfigureTransition(persistUser.Done, ensureFetchWorkspaceFeaturesSucceeded);

            transitions.ConfigureTransition(ensureFetchWorkspaceFeaturesSucceeded.Done, persistWorkspaceFeatures);
            transitions.ConfigureTransition(persistWorkspaceFeatures.Done, ensureFetchPreferencesSucceeded);

            transitions.ConfigureTransition(ensureFetchPreferencesSucceeded.Done, persistPreferences);
            transitions.ConfigureTransition(persistPreferences.Done, ensureFetchTagsSucceeded);

            transitions.ConfigureTransition(ensureFetchTagsSucceeded.Done, persistTags);
            transitions.ConfigureTransition(persistTags.Done, updateTagsSinceDate);
            transitions.ConfigureTransition(updateTagsSinceDate.Done, ensureFetchClientsSucceeded);

            transitions.ConfigureTransition(ensureFetchClientsSucceeded.Done, persistClients);
            transitions.ConfigureTransition(persistClients.Done, updateClientsSinceDate);
            transitions.ConfigureTransition(updateClientsSinceDate.Done, ensureFetchProjectsSucceeded);

            transitions.ConfigureTransition(ensureFetchProjectsSucceeded.Done, persistProjects);
            transitions.ConfigureTransition(persistProjects.Done, updateProjectsSinceDate);
            transitions.ConfigureTransition(updateProjectsSinceDate.Done, ensureFetchTasksSucceeded);

            transitions.ConfigureTransition(ensureFetchTasksSucceeded.Done, persistTasks);
            transitions.ConfigureTransition(persistTasks.Done, updateTasksSinceDate);
            transitions.ConfigureTransition(updateTasksSinceDate.Done, ensureFetchTimeEntriesSucceeded);

            transitions.ConfigureTransition(ensureFetchTimeEntriesSucceeded.Done, createProjectPlaceholders);
            transitions.ConfigureTransition(createProjectPlaceholders.Done, persistTimeEntries);
            transitions.ConfigureTransition(persistTimeEntries.Done, updateTimeEntriesSinceDate);
            transitions.ConfigureTransition(updateTimeEntriesSinceDate.Done, refetchInaccessibleProjects);
            transitions.ConfigureTransition(refetchInaccessibleProjects.FetchNext, refetchInaccessibleProjects);

            transitions.ConfigureTransition(refetchInaccessibleProjects.Done, noDefaultWorkspaceDetectingState);
            transitions.ConfigureTransition(noDefaultWorkspaceDetectingState.NoDefaultWorkspaceDetected, trySetDefaultWorkspaceState);
            transitions.ConfigureTransition(noDefaultWorkspaceDetectingState.Done, new DeadEndState());
            transitions.ConfigureTransition(trySetDefaultWorkspaceState.Done, new DeadEndState());

            // fail for server errors
            transitions.ConfigureTransition(ensureFetchWorkspacesSucceeded.ErrorOccured, new FailureState());
            transitions.ConfigureTransition(ensureFetchUserSucceeded.ErrorOccured, new FailureState());
            transitions.ConfigureTransition(ensureFetchWorkspaceFeaturesSucceeded.ErrorOccured, new FailureState());
            transitions.ConfigureTransition(ensureFetchPreferencesSucceeded.ErrorOccured, new FailureState());
            transitions.ConfigureTransition(ensureFetchTagsSucceeded.ErrorOccured, new FailureState());
            transitions.ConfigureTransition(ensureFetchClientsSucceeded.ErrorOccured, new FailureState());
            transitions.ConfigureTransition(ensureFetchProjectsSucceeded.ErrorOccured, new FailureState());
            transitions.ConfigureTransition(ensureFetchTasksSucceeded.ErrorOccured, new FailureState());
            transitions.ConfigureTransition(ensureFetchTimeEntriesSucceeded.ErrorOccured, new FailureState());
            transitions.ConfigureTransition(refetchInaccessibleProjects.ErrorOccured, new FailureState());

            // delay loop
            transitions.ConfigureTransition(delayState.Done, fetchAllSince);
        }