package com.atlassian.bitbucket.scm.event;

import com.atlassian.bitbucket.scm.Scm;
import com.atlassian.bitbucket.scm.ScmStatus;

import javax.annotation.Nonnull;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Raised when the {@link ScmStatus status} of an {@link Scm SCM} changes at runtime.
 * <p>
 * When an {@link Scm SCM} determines its initial status, it should <i>not</i> raise this event. Instead, this should
 * only be raised when something causes the plugin's SCM status to change after it has already started. For example, if
 * an SCM starts out as {@link ScmStatus#isAvailable() unavailable} because required SCM files have not been installed
 * and a system administrator installs those files, the SCM may detect the change and update its status accordingly.
 * <p>
 * Note: This event is an <i>optimisation</i>. SCMs are not required to support changing their status at runtime.
 *
 * @see Scm#getStatus()
 */
public class ScmStatusChangedEvent extends ScmEvent {

    private final ScmStatus previousStatus;

    /**
     * Constructs a new {@code ScmStatusChangedEvent}, initialising the {@code source} and setting the {@link Scm}
     * whose status has changed and the {@link ScmStatus status} the SCM used to have. The {@code previousStatus}
     * is <i>required</i>, to allow event listeners to determine when the availability of an SCM changes.
     *
     * @param source         the component within the SCM raising the event
     * @param scm            the {@link Scm SCM} whose status has changed, used to retrieve the current status
     * @param previousStatus the {@link ScmStatus status} the SCM <i>used to</i> have
     * @throws NullPointerException if the {@code source}, {@code scm} or {@code previousStatus} is {@code null}
     */
    public ScmStatusChangedEvent(@Nonnull Object source, @Nonnull Scm scm, @Nonnull ScmStatus previousStatus) {
        super(source, scm);

        this.previousStatus = checkNotNull(previousStatus, "previousStatus");
    }

    /**
     * Retrieves the <i>previous</i> {@link ScmStatus status} for the {@link Scm SCM}. The current status may be
     * retrieved using {@link #getScm()}{@link Scm#getStatus() .getStatus()}.
     *
     * @return the previous status for the SCM
     */
    @Nonnull
    public ScmStatus getPreviousStatus() {
        return previousStatus;
    }
}
