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

import org.slf4j.event.Level;

import javax.annotation.Nonnull;

import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
import static org.springframework.core.annotation.AnnotationUtils.getDefaultValue;

public class MeshClusterConfig {

    private final boolean authenticationEnabled;
    private final Level logLevel;
    private final int shardsPerNode;
    private final int size;

    private MeshClusterConfig(Builder builder) {
        authenticationEnabled = builder.authenticationEnabled;
        logLevel = builder.logLevel;
        shardsPerNode = builder.shardsPerNode;
        size = builder.size;
    }

    @Nonnull
    public static MeshClusterConfig forAnnotation(@Nonnull MeshCluster annotation) {
        requireNonNull(annotation, "annotation");

        return new Builder(annotation.size() == -1 ? annotation.value() : annotation.size())
                .authenticationEnabled(annotation.authenticationEnabled())
                .logLevel(annotation.logLevel())
                .shardsPerNode(annotation.shardsPerNode())
                .build();
    }

    @Nonnull
    public Level getLogLevel() {
        return logLevel;
    }

    public int getShardsPerNode() {
        return shardsPerNode;
    }

    public int getSize() {
        return size;
    }

    public boolean isAuthenticationEnabled() {
        return authenticationEnabled;
    }

    public static class Builder {

        private final int size;

        private boolean authenticationEnabled;
        private Level logLevel;
        private int shardsPerNode;

        @SuppressWarnings("ConstantConditions")
        public Builder(int size) {
            checkArgument(size > 0, "The cluster size must be >= 1");
            this.size = size;

            authenticationEnabled = (Boolean) getDefaultValue(MeshCluster.class, "authenticationEnabled");
            logLevel = (Level) getDefaultValue(MeshCluster.class, "logLevel");
            shardsPerNode = (Integer) getDefaultValue(MeshCluster.class, "shardsPerNode");
        }

        @Nonnull
        public Builder authenticationEnabled(boolean value) {
            authenticationEnabled = value;

            return this;
        }

        @Nonnull
        public MeshClusterConfig build() {
            return new MeshClusterConfig(this);
        }

        @Nonnull
        public Builder logLevel(@Nonnull Level value) {
            logLevel = requireNonNull(value, "logLevel");

            return this;
        }

        @Nonnull
        public Builder shardsPerNode(int value) {
            shardsPerNode = value;

            return this;
        }
    }
}
