/*
 * 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.meecrowave.cxf;

import static java.util.Collections.singletonList;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toList;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonBuilderFactory;
import javax.json.JsonMergePatch;
import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonPatch;
import javax.json.JsonPatchBuilder;
import javax.json.JsonPointer;
import javax.json.JsonReader;
import javax.json.JsonReaderFactory;
import javax.json.JsonString;
import javax.json.JsonStructure;
import javax.json.JsonValue;
import javax.json.JsonWriter;
import javax.json.JsonWriterFactory;
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
import javax.json.spi.JsonProvider;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonGeneratorFactory;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParserFactory;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;

import org.apache.cxf.bus.extension.ExtensionManagerBus;
import org.apache.cxf.bus.managers.ClientLifeCycleManagerImpl;
import org.apache.cxf.endpoint.ClientLifeCycleManager;
import org.apache.johnzon.core.AbstractJsonFactory;
import org.apache.johnzon.core.JsonGeneratorFactoryImpl;
import org.apache.johnzon.core.JsonParserFactoryImpl;
import org.apache.johnzon.jaxrs.DelegateProvider;
import org.apache.johnzon.jaxrs.JsrMessageBodyReader;
import org.apache.johnzon.jaxrs.JsrMessageBodyWriter;
import org.apache.johnzon.jaxrs.jsonb.jaxrs.JsonbJaxrsProvider;
import org.apache.meecrowave.Meecrowave;

public class ConfigurableBus extends ExtensionManagerBus {
    public void initProviders(final Meecrowave.Builder builder,
                              final ClassLoader loader) {
        final List<Object> providers =
                ofNullable(builder.getJaxrsDefaultProviders())
                        .map(s -> Stream.of(s.split(" *, *"))
                                .map(String::trim)
                                .filter(p -> !p.isEmpty())
                                .map(name -> {
                                    try {
                                        return Thread.currentThread().getContextClassLoader().loadClass(name).newInstance();
                                    } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
                                        throw new IllegalArgumentException(name + " can't be created");
                                    }
                                })
                                .collect(Collectors.<Object>toList()))
                        .orElseGet(() -> {
                            // ensure both providers share the same memory reuse logic
                            final JsonProvider provider = JsonProvider.provider();
                            final JsonReaderFactory readerFactory = provider.createReaderFactory(
                                    new HashMap<String, Object>() {{
                                        put(JsonParserFactoryImpl.SUPPORTS_COMMENTS, builder.isJsonpSupportsComment());
                                        Optional.of(builder.getJsonpMaxStringLen()).filter(v -> v > 0)
                                                .ifPresent(s -> put(JsonParserFactoryImpl.MAX_STRING_LENGTH,
                                                        s));
                                        Optional.of(builder.getJsonpMaxReadBufferLen()).filter(v -> v > 0)
                                                .ifPresent(s -> put(JsonParserFactoryImpl.BUFFER_LENGTH,
                                                        s));
                                        ofNullable(builder.getJsonpBufferStrategy()).ifPresent(
                                                s -> put(AbstractJsonFactory.BUFFER_STRATEGY, s));
                                    }});
                            final JsonWriterFactory writerFactory = provider.createWriterFactory(
                                    new HashMap<String, Object>() {{
                                        put(JsonGenerator.PRETTY_PRINTING, builder.isJsonpPrettify());
                                        Optional.of(builder.getJsonpMaxWriteBufferLen()).filter(v -> v > 0)
                                                .ifPresent(v -> put(
                                                        JsonGeneratorFactoryImpl
                                                                .GENERATOR_BUFFER_LENGTH,
                                                        v));
                                        ofNullable(builder.getJsonpBufferStrategy()).ifPresent(
                                                s -> put(AbstractJsonFactory.BUFFER_STRATEGY, s));
                                    }});
                            return Stream.<Object>of(
                                    new ConfiguredJsonbJaxrsProvider(
                                            builder.getJsonbEncoding(), builder.isJsonbNulls(),
                                            builder.isJsonbIJson(), builder.isJsonbPrettify(),
                                            builder.getJsonbBinaryStrategy(), builder.getJsonbNamingStrategy(),
                                            builder.getJsonbOrderStrategy(),
                                            new DelegateJsonProvider(provider, readerFactory, writerFactory)),
                                    new ConfiguredJsrProvider(readerFactory, writerFactory))
                                    .collect(toList());
                        });

        if (builder.isJaxrsAutoActivateBeanValidation()) {
            try { // we don't need the jaxrsbeanvalidationfeature since bean validation cdi extension handles it normally
                loader.loadClass("javax.validation.Validation");
                final Object instance = loader.loadClass("org.apache.cxf.jaxrs.validation.ValidationExceptionMapper")
                        .getConstructor().newInstance();
                instance.getClass().getGenericInterfaces(); // validate bval can be used, check NoClassDefFoundError javax.validation.ValidationException
                providers.add(instance);
            } catch (final Exception | NoClassDefFoundError e) {
                // no-op
            }
        }

        // client
        if (getProperty("org.apache.cxf.jaxrs.bus.providers") == null) {
            setProperty("skip.default.json.provider.registration", "true");
            setProperty("org.apache.cxf.jaxrs.bus.providers", providers);
        }
    }

    public void addClientLifecycleListener() {
        ClientLifeCycleManager manager = getExtension(ClientLifeCycleManager.class);
        if (manager == null) {
            manager = new ClientLifeCycleManagerImpl();
            setExtension(manager, ClientLifeCycleManager.class);
        }
        manager.registerListener(new MeecrowaveClientLifecycleListener());
    }

    @Provider
    @Produces({MediaType.APPLICATION_JSON, "application/*+json"})
    @Consumes({MediaType.APPLICATION_JSON, "application/*+json"})
    public static class ConfiguredJsonbJaxrsProvider<T> extends JsonbJaxrsProvider<T> {
        private final Jsonb jsonb;

        private ConfiguredJsonbJaxrsProvider(final String encoding,
                                             final boolean nulls,
                                             final boolean iJson,
                                             final boolean pretty,
                                             final String binaryStrategy,
                                             final String namingStrategy,
                                             final String orderStrategy,
                                             final JsonProvider provider) {
            // ATTENTION this is only a workaround for MEECROWAVE-49 and shall get removed after Johnzon has a fix for it!
            // We add byte[] to the ignored types.
            super(singletonList("[B"));
            ofNullable(encoding).ifPresent(this::setEncoding);
            ofNullable(namingStrategy).ifPresent(this::setPropertyNamingStrategy);
            ofNullable(orderStrategy).ifPresent(this::setPropertyOrderStrategy);
            ofNullable(binaryStrategy).ifPresent(this::setBinaryDataStrategy);
            setNullValues(nulls);
            setIJson(iJson);
            setPretty(pretty);
            this.jsonb = JsonbBuilder.newBuilder()
                    .withProvider(provider)
                    .withConfig(config)
                    .build();
        }

        @Override
        protected Jsonb createJsonb() {
            return jsonb;
        }
    }

    @Provider
    @Produces({MediaType.APPLICATION_JSON, "application/*+json"})
    @Consumes({MediaType.APPLICATION_JSON, "application/*+json"})
    public static class ConfiguredJsrProvider extends DelegateProvider<JsonStructure> { // TODO: probably wire the encoding in johnzon
        private ConfiguredJsrProvider(final JsonReaderFactory readerFactory,
                                      final JsonWriterFactory writerFactory) {
            super(new JsrMessageBodyReader(readerFactory, false), new JsrMessageBodyWriter(writerFactory, false));
        }
    }

    private static class DelegateJsonProvider extends JsonProvider {
        private final JsonReaderFactory readerFactory;
        private final JsonWriterFactory writerFactory;
        private final JsonProvider provider;

        private DelegateJsonProvider(final JsonProvider provider, final JsonReaderFactory readerFactory, final JsonWriterFactory writerFactory) {
            this.provider = provider;
            this.readerFactory = readerFactory;
            this.writerFactory = writerFactory;
        }

        @Override
        public JsonWriterFactory createWriterFactory(final Map<String, ?> config) {
            return writerFactory;
        }

        @Override
        public JsonReaderFactory createReaderFactory(final Map<String, ?> config) {
            return readerFactory;
        }

        @Override
        public JsonParser createParser(final Reader reader) {
            return provider.createParser(reader);
        }

        @Override
        public JsonParser createParser(final InputStream in) {
            return provider.createParser(in);
        }

        @Override
        public JsonParserFactory createParserFactory(final Map<String, ?> config) {
            return provider.createParserFactory(config);
        }

        @Override
        public JsonGenerator createGenerator(final Writer writer) {
            return provider.createGenerator(writer);
        }

        @Override
        public JsonGenerator createGenerator(final OutputStream out) {
            return provider.createGenerator(out);
        }

        @Override
        public JsonGeneratorFactory createGeneratorFactory(final Map<String, ?> config) {
            return provider.createGeneratorFactory(config);
        }

        @Override
        public JsonReader createReader(final Reader reader) {
            return provider.createReader(reader);
        }

        @Override
        public JsonReader createReader(final InputStream in) {
            return provider.createReader(in);
        }

        @Override
        public JsonWriter createWriter(final Writer writer) {
            return provider.createWriter(writer);
        }

        @Override
        public JsonWriter createWriter(final OutputStream out) {
            return provider.createWriter(out);
        }

        @Override
        public JsonObjectBuilder createObjectBuilder() {
            return provider.createObjectBuilder();
        }

        @Override
        public JsonObjectBuilder createObjectBuilder(final JsonObject jsonObject) {
            return provider.createObjectBuilder(jsonObject);
        }

        @Override
        public JsonObjectBuilder createObjectBuilder(final Map<String, Object> map) {
            return provider.createObjectBuilder(map);
        }

        @Override
        public JsonArrayBuilder createArrayBuilder() {
            return provider.createArrayBuilder();
        }

        @Override
        public JsonArrayBuilder createArrayBuilder(final JsonArray initialData) {
            return provider.createArrayBuilder(initialData);
        }

        @Override
        public JsonArrayBuilder createArrayBuilder(final Collection<?> initialData) {
            return provider.createArrayBuilder(initialData);
        }

        @Override
        public JsonPointer createPointer(final String path) {
            return provider.createPointer(path);
        }

        @Override
        public JsonBuilderFactory createBuilderFactory(final Map<String, ?> config) {
            return provider.createBuilderFactory(config);
        }

        @Override
        public JsonString createValue(final String value) {
            return provider.createValue(value);
        }

        @Override
        public JsonNumber createValue(final int value) {
            return provider.createValue(value);
        }

        @Override
        public JsonNumber createValue(final long value) {
            return provider.createValue(value);
        }

        @Override
        public JsonNumber createValue(final double value) {
            return provider.createValue(value);
        }

        @Override
        public JsonNumber createValue(final BigDecimal value) {
            return provider.createValue(value);
        }

        @Override
        public JsonNumber createValue(final BigInteger value) {
            return provider.createValue(value);
        }

        @Override
        public JsonPatch createPatch(final JsonArray array) {
            return provider.createPatch(array);
        }

        @Override
        public JsonPatch createDiff(final JsonStructure source, final JsonStructure target) {
            return provider.createDiff(source, target);
        }

        @Override
        public JsonPatchBuilder createPatchBuilder() {
            return provider.createPatchBuilder();
        }

        @Override
        public JsonPatchBuilder createPatchBuilder(final JsonArray initialData) {
            return provider.createPatchBuilder(initialData);
        }

        @Override
        public JsonMergePatch createMergePatch(final JsonValue patch) {
            return provider.createMergePatch(patch);
        }

        @Override
        public JsonMergePatch createMergeDiff(final JsonValue source, final JsonValue target) {
            return provider.createMergeDiff(source, target);
        }
    }
}
