package com.atlassian.bitbucket.mesh.client;

import com.atlassian.bitbucket.mesh.git.GitPackFile;
import com.atlassian.bitbucket.mesh.network.ConnectivitySummary;
import com.atlassian.bitbucket.mesh.network.MeshNode;
import com.atlassian.bitbucket.mesh.repair.RepairSummary;
import com.atlassian.bitbucket.mesh.repository.Repository;
import com.atlassian.bitbucket.mesh.transaction.ReplicaConsistencyVerifier;
import com.atlassian.bitbucket.mesh.transaction.ReplicaTransaction;

import javax.annotation.Nonnull;

public interface MeshClient {

    /**
     * Fetches a pack with the objects described by {@code parameters} from the {@code repository} replica on the
     * provided {@code node} and stores the pack in this node's repository replica.
     *
     * @param node       the node to fetch from
     * @param repository the repository to fetch from/to
     * @param parameters describes the objects to fetch
     * @return a result object that provides access to the pack on disk and can be used to remove the pack's
     *         {@link FetchObjectsParameters#isKeep() .keep file} that protects the pack from concurrent garbage
     *         collection
     */
    @Nonnull
    GitPackFile fetchObjects(@Nonnull MeshNode node, @Nonnull Repository repository,
                             @Nonnull FetchObjectsParameters parameters);

    /**
     * Perform a ping on a node and determine whether it is reachable and if not what error is causing the failure.
     *
     * @param node the target node to perform the ping on
     * @return the connectivity summary result of the ping
     */
    @Nonnull
    ConnectivitySummary ping(@Nonnull MeshNode node);

    /**
     * Repairs the replica of the provided {@code repository} on {@code node} from the local repository replica.
     *
     * @param node         the node whose replica should be repaired
     * @param parameters   parameters describing the repair operation to perform
     * @return             summary that describes whether the replica was successfully repaired
     */
    @Nonnull
    RepairSummary repair(@Nonnull MeshNode node, @Nonnull RepairRepositoryParameters parameters);

    /**
     * Repairs this node's replica of the provided {@code repository} from the repository replica on {@code node}.
     *
     * @param node         the node to use as the up-to-date source
     * @param parameters   parameters describing the repair operation to perform
     * @return             summary that describes whether the replica was successfully repaired
     */
    @Nonnull
    RepairSummary repairMe(@Nonnull MeshNode node, @Nonnull RepairRepositoryParameters parameters);

    /**
     * Initiates replication with the specified node, returning a handle to the replica's transaction. The returned
     * transaction <i>is not complete</i>, and requires further coordination.
     *
     * @param node       the node to replicate the transaction to
     * @param parameters parameters describing the transaction being replicated
     * @return a handle to the replica's transaction, which is used to coordinate replication
     */
    @Nonnull
    ReplicaTransaction replicate(@Nonnull MeshNode node, @Nonnull ReplicateParameters parameters);

    /**
     * Initiates replica state verification with the specified node, returning a {@link ReplicaConsistencyVerifier}
     * that serves as a handle to the replica's subprocess. The returned verifier requires further coordination to
     * complete the replica state verification process across all replica nodes.
     *
     * @param node       the node to initiate replica state verification with
     * @param parameters parameters describing the replica state verification 'transaction'
     * @return a handle to the replica's verification process
     * @since 1.2
     */
    @Nonnull
    ReplicaConsistencyVerifier verifyConsistency(@Nonnull MeshNode node,
                                                 @Nonnull ReplicateParameters parameters);
}
