/*
 * 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.karaf.features.internal.util;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;

/**
 */
public final class JsonWriter {

    private JsonWriter() {
    }

    public static void write(OutputStream stream, Object value) throws IOException {
        write(stream, value, false);
    }

    public static void write(OutputStream stream, Object value, boolean format) throws IOException {
        Writer writer = new OutputStreamWriter(stream);
        write(writer, value, format);
        writer.flush();
    }

    public static void write(Writer writer, Object value) throws IOException {
        write(writer, value, false);
    }

    public static void write(Writer writer, Object value, boolean format) throws IOException {
        int indent = format ? 0 : -1;
        write(writer, value, indent);
    }

    private static void write(Writer writer, Object value, int indent) throws IOException {
        if (value instanceof Map) {
            writeObject(writer, (Map) value, indent);
        } else if (value instanceof Collection) {
            writeArray(writer, (Collection) value, indent);
        } else if (value instanceof Number) {
            writeNumber(writer, (Number) value);
        } else if (value instanceof String) {
            writeString(writer, (String) value);
        } else if (value instanceof Boolean) {
            writeBoolean(writer, (Boolean) value);
        } else if (value == null) {
            writeNull(writer);
        } else {
            throw new IllegalArgumentException("Unsupported value: " + value);
        }
    }

    private static void writeObject(Writer writer, Map<?, ?> value, int indent) throws IOException {
        writer.append('{');
        boolean first = true;
        for (Map.Entry entry : value.entrySet()) {
            if (!first) {
                writer.append(',');
            } else {
                first = false;
            }
            if (indent >= 0) {
                indent(writer, indent + 1);
            }
            writeString(writer, (String) entry.getKey());
            if (indent >= 0) {
                writer.append(' ');
            }
            writer.append(':');
            if (indent >= 0) {
                writer.append(' ');
            }
            write(writer, entry.getValue(), indent + 1);
        }
        if (indent >= 0) {
            indent(writer, indent);
        }
        writer.append('}');
    }

    private static void writeString(Writer writer, String value) throws IOException {
        writer.append('"');
        for (int i = 0; i < value.length(); i++) {
            char c = value.charAt(i);
            switch (c) {
            case '\"':
                writer.append("\\\"");
                break;
            case '\\':
                writer.append("\\\\");
                break;
            case '\b':
                writer.append("\\b");
                break;
            case '\f':
                writer.append("\\f");
                break;
            case '\n':
                writer.append("\\n");
                break;
            case '\r':
                writer.append("\\r");
                break;
            case '\t':
                writer.append("\\t");
                break;
            default:
                if (c < ' ' || (c >= '\u0080' && c < '\u00a0') || (c >= '\u2000' && c < '\u2100')) {
                    String s = Integer.toHexString(c);
                    writer.append('\\');
                    writer.append('u');
                    for (int j = s.length(); j < 4; j++) {
                        writer.append('0');
                    }
                    writer.append(s);
                } else {
                    writer.append(c);
                }
                break;
            }
        }
        writer.append('"');
    }

    private static void writeNumber(Writer writer, Number value) throws IOException {
        writer.append(value.toString());
    }

    private static void writeBoolean(Writer writer, Boolean value) throws IOException {
        writer.append(Boolean.toString(value));
    }

    private static void writeArray(Writer writer, Collection<?> value, int indent) throws IOException {
        writer.append('[');
        boolean first = true;
        for (Object obj : value) {
            if (!first) {
                writer.append(',');
            } else {
                first = false;
            }
            if (indent >= 0) {
                indent(writer, indent + 1);
            }
            write(writer, obj, indent + 1);
        }
        if (indent >= 0) {
            indent(writer, indent);
        }
        writer.append(']');
    }

    private static void writeNull(Writer writer) throws IOException {
        writer.append("null");
    }

    static char[] INDENT;
    static {
        INDENT = new char[1];
        Arrays.fill(INDENT, '\t');
    }

    private static void indent(Writer writer, int indent) throws IOException {
        writer.write("\n");
        while (indent > INDENT.length) {
            char[] a = new char[INDENT.length * 2];
            Arrays.fill(a, '\t');
            INDENT = a;
        }
        writer.write(INDENT, 0, indent);
    }
}
