package com.atlassian.stash.internal.server;

import com.atlassian.bitbucket.license.LicenseService;
import com.atlassian.bitbucket.server.Feature;
import com.atlassian.bitbucket.server.FeatureManager;
import com.atlassian.bitbucket.server.StandardFeature;
import com.atlassian.extras.api.bitbucket.BitbucketServerLicense;
import com.atlassian.plugin.spring.AvailableToPlugins;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.Nonnull;
import java.util.Properties;
import java.util.concurrent.ConcurrentMap;

import static java.util.Objects.requireNonNull;

@AvailableToPlugins(FeatureManager.class)
@Component("featureManager")
public class PropertyFeatureManager implements FeatureManager {

    static final String PROP_PREFIX = "feature.";

    private final Properties applicationProperties;
    private final ConcurrentMap<String, Boolean> features;

    private LicenseService licenseService;

    @Autowired
    public PropertyFeatureManager(@Qualifier("applicationProperties") Properties applicationProperties) {
        this.applicationProperties = applicationProperties;
        this.features = loadFeatures(applicationProperties);
    }

    @Override
    public boolean isAvailable(@Nonnull Feature feature) {
        requireNonNull(feature, "feature");

        if (feature.isDataCenter()) {
            BitbucketServerLicense license = licenseService.get();
            return license != null && license.isClusteringEnabled();
        }

        return true;
    }

    @Override
    public boolean isEnabled(@Nonnull Feature feature) {
        return isEnabled(feature, false);
    }

    @Override
    public boolean isEnabled(@Nonnull Feature feature, boolean defaultValue) {
        requireNonNull(feature, "feature");

        if (!isAvailable(feature)) {
            return false;
        }

        Boolean enabled = features.get(feature.getKey());
        if (enabled == null) {
            String enabledString = applicationProperties.getProperty(PROP_PREFIX + feature.getKey());
            if (enabledString != null) {
                features.putIfAbsent(feature.getKey(), Boolean.parseBoolean(enabledString));
                enabled = features.get(feature.getKey());
            } else {
                enabled = defaultValue;
            }
        }
        return enabled;
    }

    @Autowired
    public void setLicenseService(LicenseService licenseService) {
        this.licenseService = licenseService;
    }

    private static ConcurrentMap<String, Boolean> loadFeatures(final Properties properties) {
        ConcurrentMap<String, Boolean> features = Maps.newConcurrentMap();
        for (StandardFeature feature : StandardFeature.values()) {
            features.put(feature.getKey(), Boolean.parseBoolean(properties.getProperty(PROP_PREFIX + feature.getKey())));
        }
        return features;
    }
}
