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

import java.io.FilterReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;

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.cm.json.Configurations;
import org.osgi.util.converter.Converters;

public class JsonSupport {

    /**
     * Convert a json value into an object
     *
     * @param value The json value
     * @return The object or {@code null} if the provided value is {@code null} or
     *         {@code ValueType#NULL}
     */
    public static Object convertToObject(final JsonValue value) {
        if (value == null) {
            return null;
        }
        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 JsonArray array = value.asJsonArray();
            final ValueType arrayType = detectArrayType(array);
            final Object[] objArray;
            if (arrayType == ValueType.FALSE || arrayType == ValueType.TRUE) {
                objArray = new Boolean[array.size()];
            } else if (arrayType == ValueType.NUMBER) {
                objArray = new Object[array.size()];
            } else if (arrayType == ValueType.STRING || arrayType == ValueType.OBJECT) {
                objArray = new String[array.size()];
            } else {
            	objArray = null;
            }
            if (objArray != null) {
                boolean isLong = true;
                for (int i = 0; i < array.size(); i++) {
                    objArray[i] = convertToObject(array.get(i));
                    if ( arrayType == ValueType.NUMBER && !(objArray[i] instanceof Long) ) {
                        isLong = false;
                    }
                }
                if ( arrayType == ValueType.NUMBER ) {
                    if ( isLong ) {
                        return Converters.standardConverter().convert(objArray).to(Long[].class);
                    } else {
                        return Converters.standardConverter().convert(objArray).to(Double[].class);
                    }
                }
                return objArray;
            }
            return array.toString();

        // type OBJECT -> return map
        default:
            return value.asJsonObject().toString();
        }
    }

    /**
     * Detect the value type of a json array. If all elements in the array have the
     * same type, this type is returned. Otherwise {@code null} is
     * returned. For an empty array {@code ValueType#STRING} is returned.
     *
     * @param array The array
     * @return The detected type
     */
    private static ValueType detectArrayType(final JsonArray array) {
        if (array.size() == 0) {
            return ValueType.STRING;
        }
        final ValueType vt = array.get(0).getValueType();
        for (int i = 1; i < array.size(); i++) {
            final ValueType ct = array.get(i).getValueType();
            boolean isSame = false;
            if (ct == vt) {
                isSame = true;
            } else if (vt == ValueType.TRUE && ct == ValueType.FALSE) {
                isSame = true;
            } else if (vt == ValueType.FALSE && ct == ValueType.TRUE) {
                isSame = true;
            }
            if (!isSame) {
                return null;
            }
        }
        return vt;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static JsonValue convertToJson(final Object object) {
        if (object == null) {
            return JsonValue.NULL;
        } else if (object instanceof String) {
            return Json.createValue((String) object);
        } else if (object instanceof Long) {
            return Json.createValue((Long) object);
        } else if (object instanceof Integer) {
            return Json.createValue((Integer) object);
        } else if (object instanceof Short) {
            return Json.createValue((Short) object);
        } else if (object instanceof Byte) {
            return Json.createValue((Byte) object);
        } else if (object instanceof Float) {
            return Json.createValue((Float) object);
        } else if (object instanceof Double) {
            return Json.createValue((Double) object);
        } else if (object instanceof Boolean) {
            final Boolean value = (Boolean) object;
            return value ? JsonValue.TRUE : JsonValue.FALSE;
        } else if (object instanceof Map) {
            boolean valid = true;
            final JsonObjectBuilder builder = Json.createObjectBuilder();
            for (final Map.Entry<Object, Object> entry : ((Map<Object, Object>) object).entrySet()) {
                final JsonValue value = convertToJson(entry.getValue());
                if (entry.getKey() instanceof String) {
                    builder.add(entry.getKey().toString(), value);
                } else {
                    valid = false;
                    break;
                }
            }
            if (valid) {
                return builder.build();
            }
        } else if (object instanceof Collection) {
            final JsonArrayBuilder builder = Json.createArrayBuilder();
            for (final Object obj : (Collection) object) {
                builder.add(convertToJson(obj));
            }
            return builder.build();
        } else if (object.getClass().isArray()) {
            final JsonArrayBuilder builder = Json.createArrayBuilder();
            for (int i = 0; i < Array.getLength(object); i++) {
                builder.add(convertToJson(Array.get(object, i)));
            }
            return builder.build();
        }
        return Json.createValue(object.toString());
    }

    /**
     * Parse a JSON content
     *
     * @param identifier     The identifier of the JSON contents (optional)
     *
     * @param contentsReader The reader for the contents
     *
     * @return The parsed JSON object. throws IOException on failure parsing
     */
    public static JsonObject parseJson(final String identifier, final Reader contentsReader) throws IOException {
        try (final JsonReader reader = Json.createReader(Configurations.jsonCommentAwareReader(new FilterReader(contentsReader) {

            @Override
            public void close() throws IOException {
                // do not close reader
            }
        }))) {
            final JsonStructure obj = reader.read();
            if (obj != null && obj.getValueType() == ValueType.OBJECT) {
                return (JsonObject) obj;
            }
            final String msg = "Invalid JSON, no root object";
            if (identifier != null) {
                throw new IOException(identifier.concat(" : ").concat(msg));
            }
            throw new IOException(msg);
        }
    }

    /**
     * Create a reader which removes comments from the input
     * @param reader The input reader
     * @return The output reader
     * @throws IOException If something fails
     */
    public static Reader createCommentRemovingReader(final Reader reader) throws IOException {
        final String contents;
        try (final StringWriter writer = new StringWriter() ){
            final char[] buf = new char[2048];
            int l;
            while ( (l = reader.read(buf)) > 0 ) {
                writer.write(buf, 0, l);
            }
            writer.flush();
            contents = writer.toString();
        }
        final StringReader stringReader = new StringReader(removeComments(contents));
        return new FilterReader(stringReader) {

            boolean closed = false;
            @Override
            public void close() throws IOException {
                if (!closed) {
                    closed = true;
                    reader.close();
                    super.close();
                }
            }
        };
    }

    /**
     * Helper method to remove comments from JSON
     * @param comments The JSON with comments
     * @return The JSON without comments
     */
    private static String removeComments(final String comments) {
        final StringBuilder sb = new StringBuilder(comments);
        int index = 0;
        boolean insideQuote = false;
        while ( index < sb.length()) {
            switch ( sb.charAt(index) ) {
            case '"' : if ( index == 0 || sb.charAt(index - 1) != '\\') {
                           insideQuote = !insideQuote;
                       }
                       index++;
                       break;
            case '/' : if ( !insideQuote && index + 1 < sb.length()) {
                           if ( sb.charAt(index + 1) == '/') {
                               // line comment
                               int m = index + 2;
                               while ( m < sb.length() && sb.charAt(m) != '\n' ) {
                                   m++;
                               }
                               sb.delete(index, m);
                           } else if ( sb.charAt(index + 1 ) == '*') {
                               // block comment
                               int m = index + 2;
                               int newlines = 0;
                               while ( m < sb.length() && (sb.charAt(m) != '/' || sb.charAt(m - 1) != '*')) {
                                   if ( sb.charAt(m) == '\n') {
                                       newlines++;
                                   }
                                   m++;
                               }
                               if ( m == sb.length() ) {
                                   index = m; // invalid - just go to the end
                               } else {
                                   sb.delete(index,  m+1);
                                   for(int x = 0; x<newlines; x++) {
                                       sb.insert(index, '\n');
                                   }
                               }
                           }
                       }
                       index++;
                       break;
            default: index++;
            }
        }
        return sb.toString();
    }
}
