/*
 * 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.felix.configurator.impl.json;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonReader;
import javax.json.JsonString;
import javax.json.JsonStructure;
import javax.json.JsonValue;
import javax.json.JsonValue.ValueType;

import org.apache.felix.configurator.impl.model.BundleState;
import org.apache.felix.configurator.impl.model.Config;
import org.apache.felix.configurator.impl.model.ConfigPolicy;
import org.apache.felix.configurator.impl.model.ConfigurationFile;
import org.osgi.service.configurator.ConfiguratorConstants;

public class JSONUtil {

    private static final String INTERNAL_PREFIX = ":configurator:";

    private static final String PROP_RANKING = "ranking";

    private static final String PROP_POLICY = "policy";

    public static final class Report {

        public final List<String> warnings = new ArrayList<>();

        public final List<String> errors = new ArrayList<>();
    }

    /**
     * Read all configurations from a bundle
     * @param provider The bundle provider
     * @param paths The paths to read from
     * @param report The report for errors and warnings
     * @return The bundle state.
     */
    public static BundleState readConfigurationsFromBundle(final BinUtil.ResourceProvider provider,
            final Set<String> paths,
            final Report report) {
        final BundleState config = new BundleState();

        final List<ConfigurationFile> allFiles = new ArrayList<>();
        for(final String path : paths) {
            final List<ConfigurationFile> files = readJSON(provider, path, report);
            allFiles.addAll(files);
        }
        Collections.sort(allFiles);

        config.addFiles(allFiles);

        return config;
    }

    /**
     * Read all json files from a given path in the bundle
     *
     * @param provider The bundle provider
     * @param path The path
     * @param report The report for errors and warnings
     * @return A list of configuration files - sorted by url, might be empty.
     */
    public static List<ConfigurationFile> readJSON(final BinUtil.ResourceProvider provider,
            final String path,
            final Report report) {
        final List<ConfigurationFile> result = new ArrayList<>();
        final Enumeration<URL> urls = provider.findEntries(path, "*.json");
        if ( urls != null ) {
            while ( urls.hasMoreElements() ) {
                final URL url = urls.nextElement();

                final String filePath = url.getPath();
                final int pos = filePath.lastIndexOf('/');
                final String name = path + filePath.substring(pos);

                try {
                    final String contents = getResource(name, url);
                    boolean done = false;
                    final TypeConverter converter = new TypeConverter(provider);
                    try {
                        final ConfigurationFile file = readJSON(converter, name, url, provider.getBundleId(), contents, report);
                        if ( file != null ) {
                            result.add(file);
                            done = true;
                        }
                    } finally {
                        if ( !done ) {
                            converter.cleanupFiles();
                        }
                    }
                } catch ( final IOException ioe ) {
                    report.errors.add("Unable to read " + name + " : " + ioe.getMessage());
                }
            }
            Collections.sort(result);
        } else {
            report.errors.add("No configurations found at path " + path);
        }
        return result;
    }

    /**
     * Read a single JSON file
     * @param converter type converter
     * @param name The name of the file
     * @param url The url to that file or {@code null}
     * @param bundleId The bundle id of the bundle containing the file
     * @param contents The contents of the file
     * @param report The report for errors and warnings
     * @return The configuration file or {@code null}.
     */
    public static ConfigurationFile readJSON(
            final TypeConverter converter,
            final String name,
            final URL url,
            final long bundleId,
            final String contents,
            final Report report) {
        final String identifier = (url == null ? name : url.toString());
        final JsonObject json = parseJSON(name, contents, report);
        final Map<String, ?> configs = verifyJSON(name, json, url != null, report);
        if ( configs != null ) {
            final List<Config> list = readConfigurationsJSON(converter, bundleId, identifier, configs, report);
            if ( !list.isEmpty() ) {
                final ConfigurationFile file = new ConfigurationFile(url, list);

                return file;
            }
        }
        return null;
    }

    /**
     * Read the configurations JSON
     * @param converter The converter to use
     * @param bundleId The bundle id
     * @param identifier The identifier
     * @param configs The map containing the configurations
     * @param report The report for errors and warnings
     * @return The list of {@code Config}s or {@code null}
     */
    public static List<Config> readConfigurationsJSON(final TypeConverter converter,
            final long bundleId,
            final String identifier,
            final Map<String, ?> configs,
            final Report report) {
        final List<Config> configurations = new ArrayList<>();
        for(final Map.Entry<String, ?> entry : configs.entrySet()) {
            if ( ! (entry.getValue() instanceof Map) ) {
            	    if ( !entry.getKey().startsWith(INTERNAL_PREFIX) ) {
            	    	    report.errors.add("Ignoring configuration in '" + identifier + "' (not a configuration) : " + entry.getKey());
            	    }
            } else {
                @SuppressWarnings("unchecked")
                final Map<String, ?> mainMap = (Map<String, ?>)entry.getValue();
                final String pid = entry.getKey();

                int ranking = 0;
                ConfigPolicy policy = ConfigPolicy.DEFAULT;

                final Dictionary<String, Object> properties = new OrderedDictionary();
                boolean valid = true;
                for(final String mapKey : mainMap.keySet()) {
                    final Object value = mainMap.get(mapKey);

                    final boolean internalKey = mapKey.startsWith(INTERNAL_PREFIX);
                    String key = mapKey;
                    if ( internalKey ) {
                        key = key.substring(INTERNAL_PREFIX.length());
                    }
                    final int pos = key.indexOf(':');
                    String typeInfo = null;
                    if ( pos != -1 ) {
                        typeInfo = key.substring(pos + 1);
                        key = key.substring(0, pos);
                    }

                    if ( internalKey ) {
                        // no need to do type conversion based on typeInfo for internal props, type conversion is done directly below
                        if ( key.equals(PROP_RANKING) ) {
                            final Integer intObj = TypeConverter.getConverter().convert(value).defaultValue(null).to(Integer.class);
                            if ( intObj == null ) {
                                report.warnings.add("Invalid ranking for configuration in '" + identifier + "' : " + pid + " - " + value);
                            } else {
                                ranking = intObj.intValue();
                            }
                        } else if ( key.equals(PROP_POLICY) ) {
                            final String stringVal = TypeConverter.getConverter().convert(value).defaultValue(null).to(String.class);
                            if ( stringVal == null ) {
                                report.errors.add("Invalid policy for configuration in '" + identifier + "' : " + pid + " - " + value);
                            } else {
                                if ( value.equals("default") || value.equals("force") ) {
                                    policy = ConfigPolicy.valueOf(stringVal.toUpperCase());
                                } else {
                                    report.errors.add("Invalid policy for configuration in '" + identifier + "' : " + pid + " - " + value);
                                }
                            }
                        }
                    } else {
                        try {

                            final Object convertedVal = getTypedValue(converter, pid, value, typeInfo);
                            properties.put(key, convertedVal);
                        } catch ( final IOException io ) {
                            report.errors.add("Invalid value/type for configuration in '" + identifier + "' : " + pid + " - " + mapKey + " : " + io.getMessage());
                            valid = false;
                            break;
                        }
                    }
                }

                if ( valid ) {
                    final Config c = new Config(pid, properties, bundleId, ranking, policy);
                    c.setFiles(converter.flushFiles());
                    configurations.add(c);
                }
            }
        }
        return configurations;
    }

    public static JsonStructure build(final Object value) {
        if (value instanceof List) {
            @SuppressWarnings("unchecked")
            final List<Object> list = (List<Object>) value;
            final JsonArrayBuilder builder = Json.createArrayBuilder();
            for (final Object obj : list) {
                if (obj instanceof String) {
                    builder.add(obj.toString());
                } else if (obj instanceof Long) {
                    builder.add((Long) obj);
                } else if (obj instanceof Double) {
                    builder.add((Double) obj);
                } else if (obj instanceof Boolean) {
                    builder.add((Boolean) obj);
                } else if (obj instanceof Map) {
                    builder.add(build(obj));
                } else if (obj instanceof List) {
                    builder.add(build(obj));
                }

            }
            return builder.build();
        } else if (value instanceof Map) {
            @SuppressWarnings("unchecked")
            final Map<String, Object> map = (Map<String, Object>) value;
            final JsonObjectBuilder builder = Json.createObjectBuilder();
            for (final Map.Entry<String, Object> entry : map.entrySet()) {
                if (entry.getValue() instanceof String) {
                    builder.add(entry.getKey(), entry.getValue().toString());
                } else if (entry.getValue() instanceof Long) {
                    builder.add(entry.getKey(), (Long) entry.getValue());
                } else if (entry.getValue() instanceof Double) {
                    builder.add(entry.getKey(), (Double) entry.getValue());
                } else if (entry.getValue() instanceof Boolean) {
                    builder.add(entry.getKey(), (Boolean) entry.getValue());
                } else if (entry.getValue() instanceof Map) {
                    builder.add(entry.getKey(), build(entry.getValue()));
                } else if (entry.getValue() instanceof List) {
                    builder.add(entry.getKey(), build(entry.getValue()));
                }
            }
            return builder.build();
        }
        return null;
    }

    /**
     * Parse a JSON content
     * @param name The name of the file
     * @param contents The contents
     * @param report The report for errors and warnings
     * @return The parsed JSON object or {@code null} on failure,
     */
    public static JsonObject parseJSON(final String name,
            String contents,
            final Report report) {
        // minify JSON first (remove comments)
        try (final Reader in = new StringReader(contents);
             final Writer out = new StringWriter()) {
            final JSMin min = new JSMin(in, out);
            min.jsmin();
            contents = out.toString();
        } catch ( final IOException ioe) {
            report.errors.add("Invalid JSON from " + name);
            return null;
        }
        try (final JsonReader reader = Json.createReader(new StringReader(contents))) {

            final JsonStructure obj = reader.read();
            if (obj != null && obj.getValueType() == ValueType.OBJECT) {
                return (JsonObject) obj;
            }
            report.errors.add("Invalid JSON from " + name);
        }
        return null;
    }

    /**
     * Get the value of a JSON property
     * @param root The JSON Object
     * @param key The key in the JSON Obejct
     * @return The value or {@code null}
     */
    public static Object getValue(final JsonObject root, final String key) {
        if ( !root.containsKey(key) ) {
            return null;
        }
        final JsonValue value = root.get(key);
        return getValue(value);
    }

    public static Object getValue(final JsonValue value) {
        switch ( value.getValueType() ) {
            // type NULL -> return null
            case NULL : return null;
            // type TRUE or FALSE -> return boolean
            case FALSE : return false;
            case TRUE : return true;
            // type String -> return String
            case STRING : return ((JsonString)value).getString();
            // type Number -> return long or double
            case NUMBER : final JsonNumber num = (JsonNumber)value;
                          if (num.isIntegral()) {
                               return num.longValue();
                          }
                          return num.doubleValue();
            // type ARRAY -> return list and call this method for each value
            case ARRAY : final List<Object> array = new ArrayList<>();
                         for(final JsonValue x : ((JsonArray)value)) {
                             array.add(getValue(x));
                         }
                         return array;
             // type OBJECT -> return map
             case OBJECT : final Map<String, Object> map = new LinkedHashMap<>();
                           final JsonObject obj = (JsonObject)value;
                           for(final Map.Entry<String, JsonValue> entry : obj.entrySet()) {
                               map.put(entry.getKey(), getValue(entry.getValue()));
                           }
                           return map;
        }
        return null;
    }

    public static Object getTypedValue(final TypeConverter converter,
            final String pid,
            final Object value,
            final String typeInfo) throws IOException {
        Object convertedVal = converter.convert(pid, value, typeInfo);
        if ( convertedVal == null ) {
            if ( typeInfo != null ) {
                throw new IOException("Unable to convert to type " + typeInfo);
            }
            JsonStructure json = build(value);
            if ( json == null ) {
                convertedVal = value.toString();
            } else {
                // JSON Structure, this will result in a String or in an array of Strings
                if ( json.getValueType() == ValueType.ARRAY ) {
                    final JsonArray arr = (JsonArray)json;
                    final String[] val = new String[arr.size()];
                    for(int i=0;i<val.length;i++) {
                        val[i] = TypeConverter.getConverter().convert(arr.get(i)).to(String.class);
                    }
                    convertedVal = val;

                } else {
                    convertedVal = TypeConverter.getConverter().convert(value).to(String.class);
                }
            }
        }
        return convertedVal;
    }

    /**
     * Verify the JSON according to the rules
     * @param name The JSON name
     * @param root The JSON root object.
     * @param report The report for errors and warnings
     * @return JSON map with configurations or {@code null}
     */
    @SuppressWarnings("unchecked")
    public static Map<String, ?> verifyJSON(final String name,
            final JsonObject root,
            final boolean bundleResource,
            final Report report) {
        if ( root == null ) {
            return null;
        }
        final Object version = getValue(root, ConfiguratorConstants.PROPERTY_RESOURCE_VERSION);
        if ( version != null ) {

            final int v = TypeConverter.getConverter().convert(version).defaultValue(-1).to(Integer.class);
            if ( v == -1 ) {
                report.errors.add("Invalid resource version information in " + name + " : " + version);
                return null;
            }
            // we only support version 1
            if ( v != 1 ) {
                report.errors.add("Invalid resource version number in " + name + " : " + version);
                return null;
            }
        }
        if ( !bundleResource) {
            // if this is not a bundle resource
            // then version and symbolic name must be set
            final Object rsrcVersion = getValue(root, ConfiguratorConstants.PROPERTY_VERSION);
            if ( rsrcVersion == null ) {
                report.errors.add("Missing version information in " + name);
                return null;
            }
            if ( !(rsrcVersion instanceof String) ) {
                report.errors.add("Invalid version information in " + name + " : " + rsrcVersion);
                return null;
            }
            final Object rsrcName = getValue(root, ConfiguratorConstants.PROPERTY_SYMBOLIC_NAME);
            if ( rsrcName == null ) {
                report.errors.add("Missing symbolic name information in " + name);
                return null;
            }
            if ( !(rsrcName instanceof String) ) {
                report.errors.add("Invalid symbolic name information in " + name + " : " + rsrcName);
                return null;
            }
        }
        return (Map<String, ?>) getValue(root);
    }

    /**
     * Read the contents of a resource, encoded as UTF-8
     * @param name The resource name
     * @param url The resource URL
     * @return The contents
     * @throws IOException If anything goes wrong
     */
    public static String getResource(final String name, final URL url)
    throws IOException {
        final URLConnection connection = url.openConnection();

        try(final BufferedReader in = new BufferedReader(
                new InputStreamReader(
                    connection.getInputStream(), "UTF-8"))) {

            final StringBuilder sb = new StringBuilder();
            String line;

            while ((line = in.readLine()) != null) {
                sb.append(line);
                sb.append('\n');
            }

            return sb.toString();
        }
    }
}
