/*
 * 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.johnzon.core;


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.JsonStructure;
import javax.json.JsonValue;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParsingException;

import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;

public class JsonReaderImpl implements JsonReader {
    private final JohnzonJsonParser parser;
    private final BufferStrategy.BufferProvider<char[]> bufferProvider;
    private final RejectDuplicateKeysMode rejectDuplicateKeysMode;
    private boolean closed = false;

    private boolean subStreamReader;

    public JsonReaderImpl(final JsonParser parser, final BufferStrategy.BufferProvider<char[]> bufferProvider,
                          final RejectDuplicateKeysMode rejectDuplicateKeysMode) {
        this(parser, false, bufferProvider, rejectDuplicateKeysMode);
    }

    /**
     * @param parser json parser.
     * @param subStreamReader {@code true} if the Stream already got started and the first
     *           operation should not be next() but {@link JohnzonJsonParser#current()} instead.
     * @param bufferProvider buffer provider for toString of created instances.
     */
    public JsonReaderImpl(final JsonParser parser, boolean subStreamReader,
                          final BufferStrategy.BufferProvider<char[]> bufferProvider,
                          final RejectDuplicateKeysMode rejectDuplicateKeys) {
        this.bufferProvider = bufferProvider;
        if (parser instanceof JohnzonJsonParser) {
            this.parser = (JohnzonJsonParser) parser;
        } else {
            this.parser = new JohnzonJsonParser.JohnzonJsonParserWrapper(parser);
        }

        this.subStreamReader = subStreamReader;
        this.rejectDuplicateKeysMode = rejectDuplicateKeys;
    }

    @Override
    public JsonStructure read() {
        return JsonStructure.class.cast(readValue());
    }

    @Override
    public JsonValue readValue() {
        checkClosed();

        if (!parser.hasNext()) {
            throw new NothingToRead();
        }


        final JsonParser.Event next;
        if (subStreamReader) {
            next = parser.current();
        } else {
            next = parser.next();
        }

        switch (next) {
            case START_OBJECT:
                final JsonObjectBuilder objectBuilder = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode);
                parseObject(objectBuilder);
                if (!subStreamReader && parser.hasNext()) {
                    throw new JsonParsingException("Expected end of file", parser.getLocation());
                }
                return objectBuilder.build();
            case START_ARRAY:
                final JsonArrayBuilder arrayBuilder = new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode);
                parseArray(arrayBuilder);
                if (!subStreamReader && parser.hasNext()) {
                    throw new JsonParsingException("Expected end of file", parser.getLocation());
                }
                return arrayBuilder.build();
            case VALUE_STRING:
                final JsonStringImpl string = new JsonStringImpl(parser.getString());
                if (!subStreamReader && parser.hasNext()) {
                    throw new JsonParsingException("Expected end of file", parser.getLocation());
                }
                return string;
            case VALUE_FALSE:
                if (!subStreamReader && parser.hasNext()) {
                    throw new JsonParsingException("Expected end of file", parser.getLocation());
                }
                return JsonValue.FALSE;
            case VALUE_TRUE:
                if (!subStreamReader && parser.hasNext()) {
                    throw new JsonParsingException("Expected end of file", parser.getLocation());
                }
                return JsonValue.TRUE;
            case VALUE_NULL:
                if (!subStreamReader && parser.hasNext()) {
                    throw new JsonParsingException("Expected end of file", parser.getLocation());
                }
                return JsonValue.NULL;
            case VALUE_NUMBER:
                final JsonNumber number;
                if (parser.isFitLong()) {
                    number = new JsonLongImpl(parser.getLong());
                } else {
                    number = new JsonNumberImpl(parser.getBigDecimal());
                }
                if (!subStreamReader && parser.hasNext()) {
                    throw new JsonParsingException("Expected end of file", parser.getLocation());
                }
                return number;
            default:
                close();
                throw new JsonParsingException("Unknown structure: " + next, parser.getLocation());
        }
    }

    @Override
    public JsonObject readObject() {
        final JsonStructure read = read();
        checkType(JsonObject.class, read);
        return JsonObject.class.cast(read);
    }

    @Override
    public JsonArray readArray() {
        final JsonStructure read = read();
        checkType(JsonArray.class, read);
        return JsonArray.class.cast(read);
    }

    private void checkType(final Class<?> expected, final JsonStructure read) {
        if (!expected.isInstance(read)) {
            throw new JsonParsingException("Expecting " + expected + " but got " + read, parser.getLocation());
        }
    }

    @Override
    public void close() {
        if (!closed) {
            closed = true;
            parser.close();
        }
    }

    private void parseObject(final JsonObjectBuilder builder) {
        String key = null;
        while (parser.hasNext()) {
            final JsonParser.Event next = parser.next();
            switch (next) {
                case KEY_NAME:
                    key = parser.getString();
                    break;

                case VALUE_STRING:
                    builder.add(key, new JsonStringImpl(parser.getString()));
                    break;

                case START_OBJECT:
                    JsonObjectBuilder subObject = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode);
                    parseObject(subObject);
                    builder.add(key, subObject);
                    break;

                case START_ARRAY:
                    JsonArrayBuilder subArray = new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode);
                    parseArray(subArray);
                    builder.add(key, subArray);
                    break;

                case VALUE_NUMBER:
                    if (parser.isIntegralNumber() && parser.isNotTooLong()) {
                        builder.add(key, new JsonLongImpl(parser.getLong()));
                    } else {
                        builder.add(key, new JsonNumberImpl(parser.getBigDecimal()));
                    }
                    break;

                case VALUE_NULL:
                    builder.addNull(key);
                    break;

                case VALUE_TRUE:
                    builder.add(key, true);
                    break;

                case VALUE_FALSE:
                    builder.add(key, false);
                    break;

                case END_OBJECT:
                    return;

                case END_ARRAY:
                    throw new JsonParsingException("']', shouldn't occur", parser.getLocation());

                default:
                    throw new JsonParsingException(next.name() + ", shouldn't occur", parser.getLocation());
            }
        }
    }

    private void parseArray(final JsonArrayBuilder builder) {
        while (parser.hasNext()) {
            final JsonParser.Event next = parser.next();
            switch (next) {
                case VALUE_STRING:
                    builder.add(new JsonStringImpl(parser.getString()));
                    break;

                case VALUE_NUMBER:
                    if (parser.isFitLong()) {
                        builder.add(new JsonLongImpl(parser.getLong()));
                    } else {
                        builder.add(new JsonNumberImpl(parser.getBigDecimal()));
                    }
                    break;

                case START_OBJECT:
                    JsonObjectBuilder subObject = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode);
                    parseObject(subObject);
                    builder.add(subObject);
                    break;

                case START_ARRAY:
                    JsonArrayBuilder subArray = null;
                    parseArray(subArray = new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode));
                    builder.add(subArray);
                    break;

                case END_ARRAY:
                    return;

                case VALUE_NULL:
                    builder.addNull();
                    break;

                case VALUE_TRUE:
                    builder.add(true);
                    break;

                case VALUE_FALSE:
                    builder.add(false);
                    break;

                case KEY_NAME:
                    throw new JsonParsingException("array doesn't have keys", parser.getLocation());

                case END_OBJECT:
                    throw new JsonParsingException("'}', shouldn't occur", parser.getLocation());

                default:
                    throw new JsonParsingException(next.name() + ", shouldn't occur", parser.getLocation());
            }
        }
    }

    private void checkClosed() {
        if (closed) {
            throw new IllegalStateException("read(), readObject(), readArray() or close() method was already called");
        }

    }

    public static class NothingToRead extends IllegalStateException {
        public NothingToRead() {
            super("Nothing to read");
        }
    }
}
