package com.atlassian.bitbucket.mesh.layout;

import com.atlassian.bitbucket.mesh.util.Version;

import javax.annotation.Nonnull;
import java.nio.file.Path;

public interface StorageLayout {

    /**
     * The version of the home layout in use. This should be updated when <i>material changes</i> are made to how
     * or where data is stored in the home directory. Database version changes are also considered material changes so a
     * backward-incompatible database upgrade warrants a version bump as well.
     * <p>
     * The version used here follows semver semantics:
     * <ul>
     *     <li>Major version increments indicate <i>backward-incompatible</i> changes have happened, which means
     *     attempts to downgrade directly to older versions should be blocked</li>
     *     <li>Minor version increments indicate <i>backward-compatible but significant</i> changes have happened</li>
     * </ul>
     * Introducing <i>new data</i>, for example, would be a minor version change--downgrading to a previous build
     * would work without issue because the older build would simply not "see" the new data.
     * <p>
     * Moving existing data to a <i>new location</i>, on the other hand, would be a major version change--downgrading
     * to a previous build would result in "losing" data, because the existing data would no longer be stored where
     * the older build expects to find it.
     * <p>
     * <i>The home layout version is not coupled to the build version.</i> It is tracked independently to allow more
     * fine-grained control over compatibility. Many minor releases, for example, do not <i>materially change</i> the
     * home layout, meaning downgrading should work without issue, and in (rare) circumstances it may be necessary for
     * a patch release to make a backward-incompatible change to the layout. Decoupling the two versions allows the
     * home layout to change as necessary.
     * <p>
     * As a result, <i>home layout major version changes may ship in any build version.</i> It is not necessary to
     * wait for a new major build version to ship a new major home layout--such changes have happened several times
     * in previous minor releases.
     * <table>
     *   <caption>Home layout versions</caption>
     *   <tr>
     *     <td>Layout version</td> <td>App version</td> <td>Details</td>
     *   </tr>
     *   <tr>
     *     <td>1</td> <td>1.0.0</td> <td>Initial home layout version</td>
     *   </tr>
     * </table>
     */
    Version HOME_LAYOUT_VERSION = new Version(1);

    String MESH_NODE_PROPERTIES = "mesh-node.properties";

    String MESH_PROPERTIES = "mesh.properties";

    @Nonnull
    Path getBinDir();

    @Nonnull
    Path getCacheDir();

    @Nonnull
    Path getConfigDir();

    @Nonnull
    Path getConfigFile();

    @Nonnull
    Path getHomeDir();

    @Nonnull
    Path getHookScriptsDir();

    @Nonnull
    Path getLogDir();

    @Nonnull
    Path getNodeConfigFile();

    @Nonnull
    Path getScriptsDir();

    @Nonnull
    Path getTempDir();
}
