/*
 * Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.internal.config;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.logging.Logger;

import javax.ws.rs.RuntimeType;
import javax.ws.rs.core.Feature;

import org.glassfish.jersey.CommonProperties;
import org.glassfish.jersey.internal.LocalizationMessages;
import org.glassfish.jersey.internal.util.PropertiesHelper;
import org.glassfish.jersey.internal.util.ReflectionHelper;
import org.glassfish.jersey.spi.ExternalConfigurationModel;

/**
 * The External Configuration Model that supports {@code System} properties. The properties are listed in a property class
 * in a form of {@code public static final String} property name. The {@code String} value of the property name is searched
 * among the {@code System} properties. The property scan is performed only when
 * {@link CommonProperties#ALLOW_SYSTEM_PROPERTIES_PROVIDER} is set to {@code true}.
 */
public class SystemPropertiesConfigurationModel implements ExternalConfigurationModel<Void> {

    private static final Logger LOGGER = Logger.getLogger(SystemPropertiesConfigurationModel.class.getName());

    private static final Map<Class, Function> converters = new HashMap<>();
    private final Map<String, Object> properties = new HashMap<>();
    private final AtomicBoolean gotProperties = new AtomicBoolean(false);
    private final List<String> propertyClassNames;
    static {
        converters.put(String.class, (Function<String, String>) s -> s);
        converters.put(Integer.class, (Function<String, Integer>) s -> Integer.valueOf(s));
        converters.put(Long.class, (Function<String, Long>) s -> Long.parseLong(s));
        converters.put(Boolean.class, (Function<String, Boolean>) s -> s.equalsIgnoreCase("1")
                ? true
                : Boolean.parseBoolean(s));
    }

    /**
     * Create new {@link ExternalConfigurationModel} for properties defined by classes in {@code propertyClassNames} list.
     * @param propertyClassNames List of property defining class names.
     */
    public SystemPropertiesConfigurationModel(List<String> propertyClassNames) {
        this.propertyClassNames = propertyClassNames;
    }

    protected List<String> getPropertyClassNames() {
        return propertyClassNames;
    }

    @Override
    public <T> T as(String name, Class<T> clazz) {
        if (converters.get(clazz) == null) {
            throw new IllegalArgumentException("Unsupported class type");
        }
        return (name != null && clazz != null && hasProperty(name))
                ? clazz.cast(converters.get(clazz).apply(getSystemProperty(name)))
                : null;
    }
    @Override
    public <T> Optional<T> getOptionalProperty(String name, Class<T> clazz) {
        return Optional.of(as(name, clazz));
    }

    @Override
    public ExternalConfigurationModel mergeProperties(Map<String, Object> inputProperties) {
        inputProperties.forEach((k, v) -> properties.put(k, v));
        return this;
    }

    @Override
    public Void getConfig() {
        return null;
    }

    @Override
    public boolean isProperty(String name) {
        String property = getSystemProperty(name);
        return property != null && (
                "0".equals(property) || "1".equals(property)
                        || "true".equalsIgnoreCase(property) || "false".equalsIgnoreCase(property)
        );
    }

    @Override
    public RuntimeType getRuntimeType() {
        return null;
    }

    @Override
    public Map<String, Object> getProperties() {
        final Boolean allowSystemPropertiesProvider = as(
                CommonProperties.ALLOW_SYSTEM_PROPERTIES_PROVIDER, Boolean.class
        );
        if (!Boolean.TRUE.equals(allowSystemPropertiesProvider)) {
            LOGGER.finer(LocalizationMessages.WARNING_PROPERTIES());
            return properties;
        }

        if (gotProperties.compareAndSet(false, true)) {
            try {
                AccessController.doPrivileged(PropertiesHelper.getSystemProperties())
                        .forEach((k, v) -> properties.put(String.valueOf(k), v));
            } catch (SecurityException se) {
                LOGGER.warning(LocalizationMessages.SYSTEM_PROPERTIES_WARNING());
                return getExpectedSystemProperties();
            }
        }
        return properties;
    }

    private Map<String, Object> getExpectedSystemProperties() {
        final Map<String, Object> result = new HashMap<>();
        for (String propertyClass : getPropertyClassNames()) {
            mapFieldsToProperties(result,
                    AccessController.doPrivileged(
                            ReflectionHelper.classForNamePA(propertyClass)
                    )
            );
        }

        return  result;
    }

    private static <T> void mapFieldsToProperties(Map<String, Object> properties, Class<T> clazz) {
        if (clazz == null) {
            return;
        }

        final Field[] fields = AccessController.doPrivileged(
                ReflectionHelper.getDeclaredFieldsPA(clazz)
        );

        for (final Field field : fields) {
            if (Modifier.isStatic(field.getModifiers()) && field.getType().isAssignableFrom(String.class)) {
                final String propertyValue = getPropertyNameByField(field);
                if (propertyValue != null) {
                    String value = getSystemProperty(propertyValue);
                    if (value != null) {
                        properties.put(propertyValue, value);
                    }
                }
            }
        }
    }

    private static String getPropertyNameByField(Field field) {
        return  AccessController.doPrivileged((PrivilegedAction<String>) () -> {
            try {
                return (String) field.get(null);
            } catch (IllegalAccessException e) {
                LOGGER.warning(e.getLocalizedMessage());
            }
            return null;
        });
    }

    private static String getSystemProperty(String name) {
        return AccessController.doPrivileged(PropertiesHelper.getSystemProperty(name));
    }

    @Override
    public Object getProperty(String name) {
        return getSystemProperty(name);
    }

    @Override
    public Collection<String> getPropertyNames() {
        return AccessController.doPrivileged(PropertiesHelper.getSystemProperties()).stringPropertyNames();
    }

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

    @Override
    public boolean isEnabled(Class<? extends Feature> featureClass) {
        return false;
    }

    @Override
    public boolean isRegistered(Object component) {
        return false;
    }

    @Override
    public boolean isRegistered(Class<?> componentClass) {
        return false;
    }

    @Override
    public Map<Class<?>, Integer> getContracts(Class<?> componentClass) {
        return null;
    }

    @Override
    public Set<Class<?>> getClasses() {
        return null;
    }

    @Override
    public Set<Object> getInstances() {
        return null;
    }

    // Jersey 2.x
    private boolean hasProperty(String name) {
        return getProperty(name) != null;
    }
}