/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sling.feature.extension.apiregions.api.config;

import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import jakarta.json.Json;
import jakarta.json.JsonArrayBuilder;
import jakarta.json.JsonException;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonValue;

import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Extension;
import org.apache.sling.feature.ExtensionState;
import org.apache.sling.feature.ExtensionType;
import org.apache.sling.feature.Feature;

/**
 * A configuration api describes the set of supported OSGi
 * configurations and framework properties. This object can be
 * stored as an extension inside a feature model.
 * This class is not thread safe.
 */
public class ConfigurationApi extends AttributeableEntity {

    /** The name of the api regions extension. */
    public static final String EXTENSION_NAME = "configuration-api";

    /**
     * Get the configuration api from the feature - if it exists.
     * If the configuration api is updated, the containing feature is left untouched.
     * {@link #setConfigurationApi(Feature, ConfigurationApi)} can be used to update
     * the feature.
     * @param feature The feature
     * @return The configuration api or {@code null}.
     * @throws IllegalArgumentException If the extension is wrongly formatted
     */
    public static ConfigurationApi getConfigurationApi(final Feature feature) {
        final Extension ext = feature == null ? null : feature.getExtensions().getByName(EXTENSION_NAME);
        return getConfigurationApi(ext);
    }

    /**
     * Get the configuration api from the extension.
     * If the configuration api is updated, the containing extension is left untouched.
     * @param ext The extension
     * @return The configuration api or {@code null} if the extension is {@code null}.
     * @throws IllegalArgumentException If the extension is wrongly formatted
     */
    public static ConfigurationApi getConfigurationApi(final Extension ext) {
        if ( ext == null ) {
            return null;
        }
        if ( ext.getType() != ExtensionType.JSON ) {
            throw new IllegalArgumentException("Extension " + ext.getName() + " must have JSON type");
        }
        try {
            final ConfigurationApi result = new ConfigurationApi();
            result.fromJSONObject(ext.getJSONStructure().asJsonObject());
            return result;
        } catch ( final IOException ioe) {
            throw new IllegalArgumentException(ioe.getMessage(), ioe);
        }
    }

    /**
     * Set the configuration api as an extension to the feature
     * @param feature The feature
     * @param api The configuration api
     * @throws IllegalStateException If the feature has already an extension of a wrong type
     * @throws IllegalArgumentException If the api configuration can't be serialized to JSON
     */
    public static void setConfigurationApi(final Feature feature, final ConfigurationApi api) {
        Extension ext = feature.getExtensions().getByName(EXTENSION_NAME);
        if ( api == null ) {
            if ( ext != null ) {
                feature.getExtensions().remove(ext);
            }
        } else {
            if ( ext == null ) {
                ext = new Extension(ExtensionType.JSON, EXTENSION_NAME, ExtensionState.OPTIONAL);
                feature.getExtensions().add(ext);
            }
            try {
                ext.setJSONStructure(api.toJSONObject());
            } catch ( final IOException ioe) {
                throw new IllegalArgumentException(ioe);
            }
        }
    }

    /** The map of configurations */
 	private final Map<String, ConfigurationDescription> configurations = new LinkedHashMap<>();

    /** The map of factory configurations */
    private final Map<String, FactoryConfigurationDescription> factories = new LinkedHashMap<>();

    /** The map of configuration additions @since 1.8 */
    private final Map<String, ConfigurationDescriptionAddition> configurationAdditions = new LinkedHashMap<>();

    /** The map of factory configuration additions @since 1.8 */
    private final Map<String, FactoryConfigurationDescriptionAddition> factoryAdditions = new LinkedHashMap<>();

    /** The map of framework properties */
    private final Map<String, FrameworkPropertyDescription> frameworkProperties = new LinkedHashMap<>();

    /** The set of internal framework property names */
    private final Set<String> internalFrameworkProperties = new TreeSet<>();

    /** The configuration region of this feature */
    private Region region;

    /** The cached region information for feature origins */
    private final Map<ArtifactId, Region> regionCache = new LinkedHashMap<>();

    /**
     * The default validation mode.
     * @since 1.2
     */
    private Mode mode;

    public ConfigurationApi() {
        this.setDefaults();
    }

    @Override
    protected void setDefaults() {
        super.setDefaults();
        this.setMode(Mode.STRICT);
    }

    /**
     * Clear the object and reset to defaults
     */
    @Override
    public void clear() {
        super.clear();
        this.configurations.clear();
        this.factories.clear();
        this.frameworkProperties.clear();
        this.internalFrameworkProperties.clear();
        this.setRegion(null);
        this.getFeatureToRegionCache().clear();
        this.getConfigurationDescriptionAdditions().clear();
        this.getFactoryConfigurationDescriptionAdditions().clear();
    }

	/**
	 * Extract the metadata from the JSON object.
	 * This method first calls {@link #clear()}.
     *
	 * @param jsonObj The JSON Object
	 * @throws IOException If JSON parsing fails
	 */
    @Override
    public void fromJSONObject(final JsonObject jsonObj) throws IOException {
        super.fromJSONObject(jsonObj);
        try {
			final String typeVal = this.getString(InternalConstants.KEY_REGION);
			if ( typeVal != null ) {
                this.setRegion(Region.valueOf(typeVal.toUpperCase()));
			}

            JsonValue val;
            val = this.getAttributes().remove(InternalConstants.KEY_CONFIGURATIONS);
            if ( val != null ) {
                for(final Map.Entry<String, JsonValue> innerEntry : val.asJsonObject().entrySet()) {
                    final ConfigurationDescription cfg = new ConfigurationDescription();
                    cfg.fromJSONObject(innerEntry.getValue().asJsonObject());
                    this.getConfigurationDescriptions().put(innerEntry.getKey(), cfg);
                }
            }

            val = this.getAttributes().remove(InternalConstants.KEY_FACTORIES);
            if ( val != null ) {
                for(final Map.Entry<String, JsonValue> innerEntry : val.asJsonObject().entrySet()) {
                    final FactoryConfigurationDescription cfg = new FactoryConfigurationDescription();
                    cfg.fromJSONObject(innerEntry.getValue().asJsonObject());
                    this.getFactoryConfigurationDescriptions().put(innerEntry.getKey(), cfg);
                }
            }

            val = this.getAttributes().remove(InternalConstants.KEY_FWK_PROPERTIES);
            if ( val != null ) {
                for(final Map.Entry<String, JsonValue> innerEntry : val.asJsonObject().entrySet()) {
                    final FrameworkPropertyDescription cfg = new FrameworkPropertyDescription();
                    cfg.fromJSONObject(innerEntry.getValue().asJsonObject());
                    this.getFrameworkPropertyDescriptions().put(innerEntry.getKey(), cfg);
                }
            }

            val = this.getAttributes().remove(InternalConstants.KEY_INTERNAL_CONFIGURATIONS);
            if ( val != null ) {
                for(final JsonValue innerVal : val.asJsonArray()) {
                    final ConfigurationDescription cfg = new ConfigurationDescription();
                    this.getConfigurationDescriptions().put(getString(innerVal), cfg);
                }
            }

            val = this.getAttributes().remove(InternalConstants.KEY_INTERNAL_FACTORIES);
            if ( val != null ) {
                for(final JsonValue innerVal : val.asJsonArray()) {
                    final FactoryConfigurationDescription cfg = new FactoryConfigurationDescription();
                    this.getFactoryConfigurationDescriptions().put(getString(innerVal), cfg);
                }
            }

            val = this.getAttributes().remove(InternalConstants.KEY_INTERNAL_FWK_PROPERTIES);
            if ( val != null ) {
                for(final JsonValue innerVal : val.asJsonArray()) {
                    this.getInternalFrameworkProperties().add(getString(innerVal));
                }
            }

            val = this.getAttributes().remove(InternalConstants.KEY_REGION_CACHE);
            if ( val != null ) {
                for(final Map.Entry<String, JsonValue> innerEntry : val.asJsonObject().entrySet()) {
                    this.getFeatureToRegionCache().put(ArtifactId.parse(innerEntry.getKey()),
                        Region.valueOf(getString(innerEntry.getValue()).toUpperCase()));
                }
            }

			final String modeVal = this.getString(InternalConstants.KEY_MODE);
			if ( modeVal != null ) {
                this.setMode(Mode.valueOf(modeVal.toUpperCase()));
			}

            val = this.getAttributes().remove(InternalConstants.KEY_CONFIGURATION_ADDITIONS);
            if ( val != null ) {
                for(final Map.Entry<String, JsonValue> innerEntry : val.asJsonObject().entrySet()) {
                    final ConfigurationDescriptionAddition cfg = new ConfigurationDescriptionAddition();
                    cfg.fromJSONObject(innerEntry.getValue().asJsonObject());
                    this.getConfigurationDescriptionAdditions().put(innerEntry.getKey(), cfg);
                }
            }

            val = this.getAttributes().remove(InternalConstants.KEY_FACTORY_ADDITIONS);
            if ( val != null ) {
                for(final Map.Entry<String, JsonValue> innerEntry : val.asJsonObject().entrySet()) {
                    final FactoryConfigurationDescriptionAddition cfg = new FactoryConfigurationDescriptionAddition();
                    cfg.fromJSONObject(innerEntry.getValue().asJsonObject());
                    this.getFactoryConfigurationDescriptionAdditions().put(innerEntry.getKey(), cfg);
                }
            }
        } catch (final JsonException | IllegalArgumentException e) {
            throw new IOException(e);
        }
    }

    /**
     * Get the configuration descriptions
	 * @return Mutable map of configuration descriptions by pid
	 */
	public Map<String, ConfigurationDescription> getConfigurationDescriptions() {
		return configurations;
	}

	/**
     * Get the factory configuration descriptions
	 * @return Mutable map of factory descriptions by factory pid
	 */
	public Map<String, FactoryConfigurationDescription> getFactoryConfigurationDescriptions() {
		return factories;
	}

	/**
     * Get the framework properties
	 * @return Mutable map of framework properties
	 */
	public Map<String, FrameworkPropertyDescription> getFrameworkPropertyDescriptions() {
		return frameworkProperties;
	}

    /**
     * Check if the configuration is an internal configuration
     * @param pid The pid
     * @return {@code true} if it is an internal configuration
     * @since 1.7.0
     */
    public boolean isInternalConfiguration(final String pid) {
        boolean result = false;
        final ConfigurationDescription desc = this.configurations.get(pid);
        if ( desc != null ) {
            result = desc.getPropertyDescriptions().isEmpty();
        }
        return result;
    }

    /**
     * Check if the factory configuration is an internal configuration
     * @param factoryPid The factory pid
     * @param name Optional name of the configuration
     * @return {@code true} if it is an internal factory configuration
     * @since 1.7.0
     */
    public boolean isInternalFactoryConfiguration(final String factoryPid, final String name) {
        boolean result = false;
        final FactoryConfigurationDescription desc = this.factories.get(factoryPid);
        if ( desc != null ) {
            result = desc.getPropertyDescriptions().isEmpty();
            if ( !result && name != null ) {
                result = desc.getInternalNames().contains(name);
            }
        }
        return result;
    }

    /**
     * Get the internal framework property names
	 * @return Mutable set of internal framework property names
	 */
	public Set<String> getInternalFrameworkProperties() {
		return internalFrameworkProperties;
    }

    /**
     * Get the api configuration region
     * @return The region or {@code null}
     */
    public Region getRegion() {
        return this.region;
    }

    /**
     * Set the api configuration region
     * @param value The region to set
     */
    public void setRegion(final Region value) {
        this.region = value;
    }

    /**
     * Detect the region, either return the stored region or the default (GLOBAL)
     * @return The region
     * @since 1.1
     */
    public Region detectRegion() {
        if ( this.getRegion() != null ) {
            return this.getRegion();
        }
        return Region.GLOBAL;
    }

    /**
     * Get the feature to region cache to keep track of regions for origin features
     * @return The cache
     * @since 1.1.
     */
    public Map<ArtifactId, Region> getFeatureToRegionCache() {
        return this.regionCache;
    }

    /**
     * Get the validation mode.
     * The default is {@link Mode#STRICT}
     * @return The mode
     * @since 1.2
     */
    public Mode getMode() {
        return this.mode;
    }

    /**
     * Set the validation mode
     * @param value The validation mode
     * @since 1.2
     */
    public void setMode(final Mode value) {
        this.mode = value == null ? Mode.STRICT : value;
    }

    /**
     * Convert this object into JSON
     *
     * @return The json object builder
     * @throws IOException If generating the JSON fails
     */
    @Override
    protected JsonObjectBuilder createJson() throws IOException {
		final JsonObjectBuilder objBuilder = super.createJson();
        if ( this.getRegion() != null ) {
            objBuilder.add(InternalConstants.KEY_REGION, this.getRegion().name());
        }
        if ( !this.getConfigurationDescriptions().isEmpty() ) {
            final JsonObjectBuilder propBuilder = Json.createObjectBuilder();
            for(final Map.Entry<String, ConfigurationDescription> entry : this.getConfigurationDescriptions().entrySet()) {
                propBuilder.add(entry.getKey(), entry.getValue().createJson());
            }
            objBuilder.add(InternalConstants.KEY_CONFIGURATIONS, propBuilder);
        }
        if ( !this.getFactoryConfigurationDescriptions().isEmpty() ) {
            final JsonObjectBuilder propBuilder = Json.createObjectBuilder();
            for(final Map.Entry<String, FactoryConfigurationDescription> entry : this.getFactoryConfigurationDescriptions().entrySet()) {
                propBuilder.add(entry.getKey(), entry.getValue().createJson());
            }
            objBuilder.add(InternalConstants.KEY_FACTORIES, propBuilder);
        }
        if ( !this.getFrameworkPropertyDescriptions().isEmpty() ) {
            final JsonObjectBuilder propBuilder = Json.createObjectBuilder();
            for(final Map.Entry<String, FrameworkPropertyDescription> entry : this.getFrameworkPropertyDescriptions().entrySet()) {
                propBuilder.add(entry.getKey(), entry.getValue().createJson());
            }
            objBuilder.add(InternalConstants.KEY_FWK_PROPERTIES, propBuilder);
        }
		if ( !this.getInternalFrameworkProperties().isEmpty() ) {
            final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
            for(final String n : this.getInternalFrameworkProperties()) {
                arrayBuilder.add(n);
            }
			objBuilder.add(InternalConstants.KEY_INTERNAL_FWK_PROPERTIES, arrayBuilder);
        }
        if ( !this.getFeatureToRegionCache().isEmpty()) {
            final JsonObjectBuilder cacheBuilder = Json.createObjectBuilder();
            for(final Map.Entry<ArtifactId, Region> entry : this.getFeatureToRegionCache().entrySet()) {
                cacheBuilder.add(entry.getKey().toMvnId(), entry.getValue().name());
            }
            objBuilder.add(InternalConstants.KEY_REGION_CACHE, cacheBuilder);
        }
        if ( this.getMode() != Mode.STRICT ) {
            objBuilder.add(InternalConstants.KEY_MODE, this.getMode().name());
        }
        if ( !this.getConfigurationDescriptionAdditions().isEmpty() ) {
            final JsonObjectBuilder propBuilder = Json.createObjectBuilder();
            for(final Map.Entry<String, ConfigurationDescriptionAddition> entry : this.getConfigurationDescriptionAdditions().entrySet()) {
                propBuilder.add(entry.getKey(), entry.getValue().createJson());
            }
            objBuilder.add(InternalConstants.KEY_CONFIGURATION_ADDITIONS, propBuilder);
        }
        if ( !this.getFactoryConfigurationDescriptionAdditions().isEmpty() ) {
            final JsonObjectBuilder propBuilder = Json.createObjectBuilder();
            for(final Map.Entry<String, FactoryConfigurationDescriptionAddition> entry : this.getFactoryConfigurationDescriptionAdditions().entrySet()) {
                propBuilder.add(entry.getKey(), entry.getValue().createJson());
            }
            objBuilder.add(InternalConstants.KEY_FACTORY_ADDITIONS, propBuilder);
        }

		return objBuilder;
    }

    /**
     * Get the map of configuration description additions
     * @return The map, might be empty
     * @since 1.8
     */
    public Map<String, ConfigurationDescriptionAddition> getConfigurationDescriptionAdditions() {
        return this.configurationAdditions;
    }

    /**
     * Get the map of factory configuration description additions
     * @return The map, might be empty
     * @since 1.8
     */
    public Map<String, FactoryConfigurationDescriptionAddition> getFactoryConfigurationDescriptionAdditions() {
        return this.factoryAdditions;
    }
}
