package com.atlassian.bitbucket.mesh.test.cluster;

import org.slf4j.event.Level;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.nio.file.Path;
import java.util.concurrent.Future;

/**
 * A {@link MeshClusterNode} that is fully managed by {@link MeshClusterManager}, including provisioning, startup and shutdown.
 *
 * @see MeshClusterManager
 */
public interface ManagedMeshClusterNode extends MeshClusterNode {

    /**
     * Waits for the node to have started and be ready to service RPC requests
     *
     * @throws IOException if an I/O error occurs
     * @throws InterruptedException if the thread was interrupted while waiting
     */
    void awaitReady() throws IOException, InterruptedException;

    /**
     * @return the node's home directory
     */
    @Nonnull
    Path getHomeDir();

    /**
     * @return the port the node's RPC services are running on
     */
    int getPort();

    /**
     * @param partition the partition ID
     * @param hierarchyId the repository hierarchy
     * @param localId the repository's local ID
     * @return the repository directory for the provided repository ID
     */
    @Nonnull
    Path getRepoDir(@Nonnull String partition, @Nonnull String hierarchyId, @Nonnull String localId);

    /**
     * @return {@code true} if this node requires provisioning and authentication; otherwise, {@code false}
     */
    boolean isAuthenticationEnabled();

    /**
     * @return {@code true} if the node is part of the cluster
     */
    boolean isPartOfCluster();

    /**
     * @return {@code true} if the node process is running; otherwise {@code false}
     */
    boolean isRunning();

    /**
     * @return {@code true} if the node was registered with the control plane; {@code false} if the node was already
     *         registered
     */
    boolean joinCluster();

    /**
     * @param stop if {@code true}, {@link #stop() stops} the node after removing it from the cluster
     * @return {@code true} if the node was unregistered from the control plane; {@code false} if the node wasn't
     *         registered to begin with
     */
    boolean leaveCluster(boolean stop);

    /**
     * Clears the data on the managed shards of the node
     */
    void reset();

    /**
     * Sets the minimum log level for log messages from the node to be forwarded to stdout
     *
     * @param level the log level
     */
    void setLogLevel(@Nonnull Level level);

    /**
     * Starts the node process
     *
     * @return a {@link Future} that completes when the node is fully started and {@link #awaitReady() available}
     *         for RPC requests
     */
    @Nonnull
    Future<Void> start();

    /**
     * Stops the Mesh node process
     */
    void stop();
}
