package com.atlassian.stash.internal.maintenance;

import javax.annotation.Nonnull;

/**
 * Decorates another {@link MaintenanceTask}, putting the system in maintenance mode before executing the delegate
 * task. Regardless of the outcome of the delegate task, the system will be unlocked.
 */
public class MaintenanceModePhase extends CompositeMaintenanceTask {

    private final JohnsonMaintenanceEvent maintenanceEvent;
    private final MaintenanceModeHelper maintenanceModeHelper;

    private MaintenanceModePhase(Step[] steps, int totalWeight, JohnsonMaintenanceEvent maintenanceEvent,
                                 MaintenanceModeHelper maintenanceModeHelper) {
        super(steps, totalWeight);

        this.maintenanceEvent = maintenanceEvent;
        this.maintenanceModeHelper = maintenanceModeHelper;
    }

    @Override
    public void run() {
        // all of the work should happen in maintenance mode and the scheduler should be paused; decorate the task we enclose
        maintenanceModeHelper.lock(maintenanceEvent);
        try {
            super.run();
        } finally {
            maintenanceModeHelper.unlock(maintenanceEvent);
        }
    }

    public static class Builder extends CompositeMaintenanceTask.AbstractBuilder<Builder> {

        private final MaintenanceModeHelper maintenanceModeHelper;

        private JohnsonMaintenanceEvent maintenanceEvent;

        public Builder(MaintenanceModeHelper maintenanceModeHelper) {
            this.maintenanceModeHelper = maintenanceModeHelper;
        }

        public Builder event(JohnsonMaintenanceEvent event) {
            this.maintenanceEvent = event;
            return this;
        }

        @Nonnull
        public MaintenanceModePhase build() {
            return new MaintenanceModePhase(steps.toArray(new Step[steps.size()]), totalWeight,
                    maintenanceEvent, maintenanceModeHelper);
        }

        protected Builder self() {
            return this;
        }
    }
}
