/*
 * 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;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonException;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonReader;
import javax.json.JsonString;
import javax.json.JsonValue;
import javax.json.JsonValue.ValueType;
import javax.json.JsonWriter;

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

/**
 * Configuration of API regions for Java API.
 * 
 * This class is not thread safe.
 */
public class ApiRegions {

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

    private static final String NAME_KEY = "name";

    private static final String EXPORTS_KEY = "exports";

    private final List<ApiRegion> regions = new ArrayList<>();

    /**
     * Return the list of regions
     *
     * @return Unmodifiable list of regions, might be empty
     */
    public List<ApiRegion> listRegions() {
        return Collections.unmodifiableList(this.regions);
    }

    /**
     * Get the root regions. The root is the region which does not have a parent
     *
     * @return The root region or {@code null}
     */
    public ApiRegion getRoot() {
        if (this.regions.isEmpty()) {
            return null;
        }
        return this.regions.get(0);
    }

    /**
     * Check if any region exists
     *
     * @return {@code true} if it has any region
     */
    public boolean isEmpty() {
        return this.regions.isEmpty();
    }

    /**
     * Add the region. The region is only added if there isn't already a region with
     * the same name
     *
     * @param region The region to add
     * @return {@code true} if the region could be added, {@code false} otherwise
     */
    public boolean add(final ApiRegion region) {
        return add(this.regions.size(), region);
    }

    /**
     * Add the region. The region is only added if there isn't already a region with
     * the same name
     *
     * @param idx The position to add
     * @param region The region to add
     * @return {@code true} if the region could be added, {@code false} otherwise
     */
    public boolean add(final int idx, final ApiRegion region) {
        for (final ApiRegion c : this.regions) {
            if (c.getName().equals(region.getName())) {
                return false;
            }
        }
        Set<ArtifactId> origins = new LinkedHashSet<>(Arrays.asList(region.getFeatureOrigins()));

        this.regions.stream()
            .filter(
                existingRegion ->
                {
                    ArtifactId[] targetOrigins = existingRegion.getFeatureOrigins();
                    return (targetOrigins.length == 0 && origins.isEmpty())
                        || Stream.of(targetOrigins).anyMatch(origins::contains);
                }
            ).reduce((a,b) -> b).ifPresent(region::setParent);

        this.regions.add(idx, region);
        return true;
    }


    /**
     * Get a named region
     *
     * @param name The name
     * @return The region or {@code null}
     */
    public ApiRegion getRegionByName(final String name) {
        ApiRegion found = null;

        for (final ApiRegion c : this.regions) {
            if (c.getName().equals(name)) {
                found = c;
                break;
            }
        }

        return found;
    }

    public ApiRegion[] getRegionsByFeature(final ArtifactId featureId) {
        return this.regions.stream().filter(
            region -> Stream.of(region.getFeatureOrigins()).anyMatch(featureId::equals)
        ).toArray(ApiRegion[]::new);
    }

    /**
     * Get the names of the regions
     *
     * @return The list of regions, might be empty
     */
    public List<String> getRegionNames() {
        final List<String> names = new ArrayList<>();
        for (final ApiRegion c : this.regions) {
            names.add(c.getName());
        }
        return Collections.unmodifiableList(names);
    }

    /**
     * Convert regions into json
     *
     * @return The json array
     * @throws IOException If generating the JSON fails
     */
    public JsonArray toJSONArray() throws IOException {
        final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();

        for (final ApiRegion region : this.regions) {
            final JsonObjectBuilder regionBuilder = Json.createObjectBuilder();
            regionBuilder.add(NAME_KEY, region.getName());

            if (!region.listExports().isEmpty()) {
                final JsonArrayBuilder expArrayBuilder = Json.createArrayBuilder();
                for (final ApiExport exp : region.listExports()) {
                    expArrayBuilder.add(exp.toJSONValue());
                }

                regionBuilder.add(EXPORTS_KEY, expArrayBuilder);
            }
            ArtifactId[] origins = region.getFeatureOrigins();
            if (origins.length > 0) {
                final JsonArrayBuilder originBuilder = Json.createArrayBuilder();
                for (ArtifactId origin : origins) {
                    originBuilder.add(origin.toMvnId());
                }
                regionBuilder.add(Artifact.KEY_FEATURE_ORIGINS, originBuilder);
            }
            for (final Map.Entry<String, String> entry : region.getProperties().entrySet()) {
                regionBuilder.add(entry.getKey(), entry.getValue());
            }

            arrayBuilder.add(regionBuilder);
        }

        return arrayBuilder.build();
    }

    /**
     * Convert regions into json
     *
     * @return The json array as a string
     * @throws IOException If generating the JSON fails
     */
    public String toJSON() throws IOException {
        final JsonArray array = this.toJSONArray();
        try (final StringWriter stringWriter = new StringWriter();
                final JsonWriter writer = Json.createWriter(stringWriter)) {
            writer.writeArray(array);
            return stringWriter.toString();
        }
    }

    /**
     * Parse a JSON array into an api regions object
     *
     * @param json The json as a string
     * @return The api regions
     * @throws IOException If the json could not be parsed
     */
    public static ApiRegions parse(final String json) throws IOException {
        try (final JsonReader reader = Json.createReader(new StringReader(json))) {
            return parse(reader.readArray());
        }
    }

    /**
     * Parse a JSON array into an api regions object
     *
     * @param json The json
     * @return The api regions
     * @throws IOException If the json could not be parsed
     */
    public static ApiRegions parse(final JsonArray json) throws IOException {
        try {
            final ApiRegions regions = new ApiRegions();

            for (final JsonValue value : json) {
                if (value.getValueType() != ValueType.OBJECT) {
                    throw new IOException("Illegal api regions json " + json);
                }
                final JsonObject obj = (JsonObject) value;

                final ApiRegion region = new ApiRegion(obj.getString(NAME_KEY));

                for (final Map.Entry<String, JsonValue> entry : obj.entrySet()) {
                    if (NAME_KEY.equals(entry.getKey())) {
                        continue; // already set
                    } else if (entry.getKey().equals(EXPORTS_KEY)) {
                        for (final JsonValue e : (JsonArray) entry.getValue()) {
                            ApiExport.fromJson(region, e);
                        }
                    } else if (entry.getKey().equals(Artifact.KEY_FEATURE_ORIGINS)) {
                        final Set<ArtifactId> origins = new LinkedHashSet<>();
                        for (final JsonValue origin : (JsonArray) entry.getValue()) {
                            origins.add(ArtifactId.fromMvnId(((JsonString) origin).getString()));
                        }
                        region.setFeatureOrigins(origins.toArray(new ArtifactId[0]));

                        // everything else is stored as a string property
                    } else {
                        region.getProperties().put(entry.getKey(), ((JsonString) entry.getValue()).getString());
                    }
                }
                if (!regions.add(region)) {
                    throw new IOException("Region " + region.getName() + " is defined twice");
                }
            }
            return regions;
        } catch (final JsonException | IllegalArgumentException e) {
            throw new IOException(e);
        }
    }

    /**
     * Get the api regions from the feature - if it exists.
     * @param feature The feature
     * @return The api regions or {@code null}.
     * @throws IllegalArgumentException If the extension is wrongly formatted
     * @since 1.1
     */
    public static ApiRegions getApiRegions(final Feature feature) {
        final Extension ext = feature == null ? null : feature.getExtensions().getByName(EXTENSION_NAME);
        return getApiRegions(ext);
    }

    /**
     * Get the api regions from the extension.
     * @param ext The extension
     * @return The api regions or {@code null}.
     * @throws IllegalArgumentException If the extension is wrongly formatted
     * @since 1.1
     */
    public static ApiRegions getApiRegions(final Extension ext) {
        if ( ext == null ) {
            return null;
        }
        if ( ext.getType() != ExtensionType.JSON ) {
            throw new IllegalArgumentException("Extension " + ext.getName() + " must have JSON type");
        }
        if ( ext.getJSONStructure() == null ) {
            return new ApiRegions();
        }
        try {
            return parse(ext.getJSONStructure().asJsonArray());
        } catch ( final IOException ioe) {
            throw new IllegalArgumentException(ioe.getMessage(), ioe);
        }
    }

    @Override
    public String toString() {
        return "ApiRegions [regions=" + regions + "]";
    }

    @Override
    public int hashCode() {
        return Objects.hash(regions);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        ApiRegions other = (ApiRegions) obj;
        return Objects.equals(regions, other.regions);
    }
}
