package com.atlassian.stash.internal.maintenance.backup;

import com.atlassian.event.api.EventPublisher;
import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.stash.internal.db.DatabaseManager;
import com.atlassian.stash.internal.maintenance.ClusterableTask;
import com.atlassian.stash.internal.maintenance.MaintenanceTask;
import com.atlassian.stash.internal.maintenance.MaintenanceTaskFactory;
import com.atlassian.stash.internal.maintenance.TaskMaintenanceEvent;
import com.atlassian.stash.internal.maintenance.latch.LatchMode;
import com.atlassian.stash.internal.maintenance.latch.LatchableService;

/**
 * Maintenance task for creating a system backup out of process (by external tools).
 *
 * @since 2.12
 */
@ClusterableTask
public class ExternalBackupTask extends AbstractBackupTask {

    public ExternalBackupTask(DatabaseManager databaseManager, EventPublisher eventPublisher, I18nService i18nService,
                              MaintenanceTaskFactory taskFactory, LatchableService... latchableServices) {
        super(databaseManager, eventPublisher, i18nService, taskFactory, latchableServices);
    }

    @Override
    protected MaintenanceTask createDelegateBackupTask(BackupClientPlaceholderStep backupClientPlaceholderStep,
                                                       MaintenanceTaskFactory taskFactory, BackupState backupState,
                                                       TaskMaintenanceEvent maintenanceEvent) {
        return taskFactory.maintenanceModePhaseBuilder()
                .event(maintenanceEvent)
                .add(taskFactory.backupPhaseBuilder(backupState)
                        .add(taskFactory.latchAndDrainDatabaseBackupStep(LatchMode.CLUSTER), 50)
                        .add(taskFactory.latchAndDrainScmStep(LatchMode.CLUSTER), 50)       //100 backup
                        .build(), 10)
                //Blocks until a '100' update from the client backup is received or until the backup is cancelled.
                //Client progress updates can be received at any time before this task executes via calls to
                //backupClientPlaceholderStep.onProgressUpdate() and will be factored into the overall progress
                .add(backupClientPlaceholderStep, 90) //100 overall
                .add(taskFactory.unlatchScmStep(LatchMode.CLUSTER), 0)
                .add(taskFactory.unlatchDatabaseStep(LatchMode.CLUSTER, null), 0)
                .build();
    }
}
