package com.atlassian.bitbucket.mesh.management;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.nio.file.Path;
import java.security.PublicKey;
import java.time.Duration;
import java.util.Map;

/**
 * Responsible for application level functionality, such as configuration management, health status, etc.
 */
public interface NodeManager {

    /**
     * Waits up to the specified {@code timeout} for {@link #updateConfiguration configuration} to be applied from
     * the control plane. This can be used to prevent RPCs and other operations from being performed in the period
     * between when the application starts and when any potentially-stale configuration has been updated.
     *
     * @param timeout the maximum amount of time to wait before returning
     * @return {@code true} if configuration has been applied; otherwise, {@code false}
     * @throws InterruptedException if the thread is interrupted while waiting
     */
    boolean awaitConfiguration(@Nonnull Duration timeout) throws InterruptedException;

    /**
     * @param parameters the parameters used from the request to determine what is included in the node's support zip
     * @return the {@link Path path} for the node's support zip
     */
    @Nonnull
    Path createSupportZip(@Nonnull CreateSupportZipParameters parameters);

    /**
     * @return this node's non-default configuration properties
     * @since 1.3
     */
    @Nonnull
    Map<String, String> getConfigurationProperties();

    /**
     * @return the ID of this Mesh node
     */
    @Nonnull
    String getId();

    /**
     * Return information about the node. Information includes but is not limited to the node version,
     * RPC version, etc.
     *
     * @return node information
     */
    @Nonnull
    Map<String, String> getNodeInfo();

    /**
     * Collect support information about Mesh. Information includes but is not limited to the git version,
     * throttling ticket stats, etc.
     *
     * @return support information
     */
    @Nonnull
    SupportInfo getSupportInfo();

    /**
     * Retrieves a flag indicating whether {@link #updateConfiguration configuration} has been applied by the
     * control plane.
     *
     * @return {@code true} if the node has been configured; otherwise, {@code false}
     */
    boolean isConfigured();

    /**
     * Provisions the node, performing the initial exchange of trust with the control plane. The control plane's
     * public key is received and persisted, and the node's public key is returned.
     * <p>
     * If authentication is disabled, the provided public key is ignored and {@code null} is returned.
     *
     * @param parameters provides the control plane's public key
     * @return the node's public key, if authentication is enabled; otherwise, {@code false}
     */
    @Nullable
    PublicKey provision(@Nonnull ProvisionParameters parameters);

    /**
     * Updates application configuration with the provided {@code parameters}.
     *
     * @param parameters describes the configuration update
     */
    void updateConfiguration(@Nonnull UpdateConfigurationParameters parameters);
}
