/*
 * 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 javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonException;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.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 framework properties */
    private final Map<String, FrameworkPropertyDescription> frameworkProperties = new LinkedHashMap<>();

    /** The set of internal configuration names */
    private final Set<String> internalConfigurations = new TreeSet<>();

    /** The set of internal factory configuration names */
    private final Set<String> internalFactories = new TreeSet<>();

    /** 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 = 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.internalConfigurations.clear();
        this.internalFactories.clear();
        this.internalFrameworkProperties.clear();
        this.setRegion(null);
        this.getFeatureToRegionCache().clear();
        this.setMode(Mode.STRICT);
    }

	/**
	 * 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()) {
                    this.getInternalConfigurations().add(getString(innerVal));
                }
            }

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

            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()));				
			}

        } 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;
	}

	/**
     * Get the internal configuration pids
	 * @return Mutable set of internal configuration pids
	 */
	public Set<String> getInternalConfigurations() {
		return internalConfigurations;
	}

	/**
     * Get the internal factory pids
	 * @return Mutable set of internal factory configuration pids
	 */
	public Set<String> getInternalFactoryConfigurations() {
		return internalFactories;
	}

	/**
     * 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
    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.getInternalConfigurations().isEmpty() ) {
            final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
            for(final String n : this.getInternalConfigurations()) {
                arrayBuilder.add(n);
            }
			objBuilder.add(InternalConstants.KEY_INTERNAL_CONFIGURATIONS, arrayBuilder);
		}
		if ( !this.getInternalFactoryConfigurations().isEmpty() ) {
            final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
            for(final String n : this.getInternalFactoryConfigurations()) {
                arrayBuilder.add(n);
            }
			objBuilder.add(InternalConstants.KEY_INTERNAL_FACTORIES, arrayBuilder);
		}
		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());
        }

		return objBuilder;
    }
}
