package com.atlassian.bitbucket.mesh.config;

import org.springframework.core.env.Environment;

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

class DefaultPackCacheConfig implements PackCacheConfig {

    static final String PROP_EVICTION_HYSTERESIS = "hosting.cache.eviction.hysteresis";
    static final String PROP_EVICTION_TRIGGER_FREE_SPACE = "hosting.cache.eviction.trigger.free.space";
    static final String PROP_EXPIRY_CHECK_INTERVAL = "hosting.cache.expiry.check.interval";
    static final String PROP_MINIMUM_FREE_SPACE = "hosting.cache.minimum.free.space";
    static final String PROP_PACK_ENABLED = "hosting.cache.pack.enabled";
    static final String PROP_PACK_MAX_COUNT = "hosting.cache.pack.maxCount";
    static final String PROP_PACK_TTL = "hosting.cache.pack.ttl";
    static final String PROP_PROTOCOL_HTTP_ENABLED = "hosting.cache.protocol.http.enabled";
    static final String PROP_PROTOCOL_SSH_ENABLED = "hosting.cache.protocol.ssh.enabled";

    private final Path cacheDir;
    private final Environment environment;

    //The current properties are kept in a separate object so they can be easily reloaded
    private volatile Settings current;

    DefaultPackCacheConfig(Environment environment, Path cacheDir) {
        this.cacheDir = cacheDir.resolve("pack");
        this.environment = environment;

        current = new Settings(environment);
    }

    @Nonnull
    @Override
    public Path getCacheDir() {
        return cacheDir;
    }

    @Override
    public long getEvictionHysteresis() {
        return current.evictionHysteresis;
    }

    @Override
    public long getEvictionTriggerFreeSpace() {
        return current.evictionTriggerFreeSpace;
    }

    @Nonnull
    @Override
    public Duration getExpiryCheckInterval() {
        return current.expiryCheckInterval;
    }

    @Override
    public int getMaxCount() {
        return current.maxCount;
    }

    @Override
    public long getMinimumFreeSpace() {
        return current.minimumFreeSpace;
    }

    @Override
    public long getTimeToLive() {
        return current.timeToLive;
    }

    @Override
    public boolean isEnabled() {
        return current.enabled;
    }

    @Override
    public boolean isEnabledForHttp() {
        Settings settings = current;
        return settings.enabled && settings.enabledForHttp;
    }

    @Override
    public boolean isEnabledForSsh() {
        Settings settings = current;
        return settings.enabled && settings.enabledForSsh;
    }

    void reload() {
        current = new Settings(environment);
    }
    
    private static class Settings {

        private final boolean enabled;
        private final boolean enabledForHttp;
        private final boolean enabledForSsh;
        private final long evictionHysteresis;
        private final long evictionTriggerFreeSpace;
        private final Duration expiryCheckInterval;
        private final int maxCount;
        private final long minimumFreeSpace;
        private final long timeToLive;
        
        Settings(Environment environment) {
            enabled = environment.getProperty(PROP_PACK_ENABLED, Boolean.class, true);
            enabledForHttp = environment.getProperty(PROP_PROTOCOL_HTTP_ENABLED, Boolean.class, true);
            enabledForSsh = environment.getProperty(PROP_PROTOCOL_SSH_ENABLED, Boolean.class, true);
            evictionHysteresis = environment.getRequiredProperty(PROP_EVICTION_HYSTERESIS, Long.class);
            evictionTriggerFreeSpace = environment.getRequiredProperty(PROP_EVICTION_TRIGGER_FREE_SPACE, Long.class);
            expiryCheckInterval = Duration.ofSeconds(environment.getRequiredProperty(PROP_EXPIRY_CHECK_INTERVAL, Long.class));
            maxCount = environment.getRequiredProperty(PROP_PACK_MAX_COUNT, Integer.class);
            minimumFreeSpace = environment.getRequiredProperty(PROP_MINIMUM_FREE_SPACE, Long.class);
            timeToLive = environment.getRequiredProperty(PROP_PACK_TTL, Long.class);
        }
    }
}
