package com.atlassian.stash.internal.profiles;

import com.atlassian.bitbucket.util.DevModeUtils;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

import java.util.Collections;
import java.util.Set;

/**
 * Uses the {@link Dev} and {@link Production} annotations to determine whether a component is enabled for
 * {@link DevModeUtils#isEnabled() dev mode} or not.
 * <p>
 * Note: If this condition is applied to a bean which is not annotated <i>the bean will not be loaded</i>.
 *
 * @see Dev
 * @see Production
 * @since 3.4
 */
public class DevModeCondition implements Condition {

    public static final String PROFILE_DEV = "dev";
    public static final String PROFILE_PROD = "production";
    public static final String PROP_PROFILES = "stash.spring.profiles";

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return (metadata.isAnnotated(Dev.class.getName()) && chooseProfiles().contains(PROFILE_DEV)) ||
                (metadata.isAnnotated(Production.class.getName()) && chooseProfiles().contains(PROFILE_PROD));
    }

    /**
     * Uses the {@code stash.spring.profiles} system property to retrieve specific profiles to activate. If set,
     * these profiles <i>supersede and ignore</i> the state of the {@code atlassian.dev.mode} flag.
     * <p>
     * The following rules are applied, in order:
     * <ol>
     *     <li>If {@code stash.spring.profiles} is set, it is taken as a comma-separated list of profiles to
     *     activate <i>regardless of {@code atlassian.dev.mode}</i></li>
     *     <li>If {@code atlassian.dev.mode} system property is set to {@code true}, the {@link #PROFILE_DEV "dev"}
     *     profile is activated</li>
     *     <li>Otherwise the {@link #PROFILE_PROD "production"} profile is activated</li>
     * </ol>
     *
     * @return the property-specified profiles, or "dev" or "production" depending on {@code atlassian.dev.mode}
     */
    private static Set<String> chooseProfiles() {
        String property = System.getProperty(PROP_PROFILES);
        if (StringUtils.isBlank(property)) {
            return DevModeUtils.isEnabled() ? Collections.singleton(PROFILE_DEV) : Collections.singleton(PROFILE_PROD);
        }
        return ImmutableSet.copyOf(property.split(","));
    }
}
