/*
 * 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 org.apache.cxf.cdi.CXFCdiServlet;
import org.apache.cxf.common.util.ReflectionUtil;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.jaxrs.JAXRSServiceFactoryBean;
import org.apache.cxf.jaxrs.model.ApplicationInfo;
import org.apache.cxf.jaxrs.model.ClassResourceInfo;
import org.apache.cxf.jaxrs.model.MethodDispatcher;
import org.apache.cxf.jaxrs.model.OperationResourceInfo;
import org.apache.cxf.jaxrs.model.ProviderInfo;
import org.apache.cxf.jaxrs.provider.ProviderFactory;
import org.apache.cxf.jaxrs.provider.ServerProviderFactory;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.transport.ChainInitiationObserver;
import org.apache.cxf.transport.http.DestinationRegistry;
import org.apache.cxf.transport.servlet.ServletDestination;
import org.apache.meecrowave.Meecrowave;
import org.apache.meecrowave.logging.tomcat.LogFacade;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.ws.rs.core.Application;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Enumeration;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Stream;

import static java.util.Optional.ofNullable;

// this look a bit complicated but it just:
// - wraps cxf in a filter to support plain resources when not conflicting with application path
// - logs resources
public class CxfCdiAutoSetup implements ServletContainerInitializer {
    private static final String NAME = "cxf-cdi";

    @Override
    public void onStartup(final Set<Class<?>> c, final ServletContext ctx) throws ServletException {
        final Meecrowave.Builder builder = Meecrowave.Builder.class.cast(ctx.getAttribute("meecrowave.configuration"));
        final MeecrowaveCXFCdiServlet delegate = new MeecrowaveCXFCdiServlet();
        final FilterRegistration.Dynamic jaxrs = ctx.addFilter(NAME, new Filter() {
            private final String servletPath = builder.getJaxrsMapping().endsWith("/*") ?
                    builder.getJaxrsMapping().substring(0, builder.getJaxrsMapping().length() - 2) : builder.getJaxrsMapping();

            @Override
            public void init(final FilterConfig filterConfig) throws ServletException {
                delegate.init(new ServletConfig() {
                    @Override
                    public String getServletName() {
                        return NAME;
                    }

                    @Override
                    public ServletContext getServletContext() {
                        return filterConfig.getServletContext();
                    }

                    @Override
                    public String getInitParameter(final String name) {
                        return filterConfig.getInitParameter(name);
                    }

                    @Override
                    public Enumeration<String> getInitParameterNames() {
                        return filterConfig.getInitParameterNames();
                    }
                });
            }

            @Override
            public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
                if (!HttpServletRequest.class.isInstance(request)) {
                    chain.doFilter(request, response);
                    return;
                }
                final HttpServletRequest http = HttpServletRequest.class.cast(request);
                final String path = http.getRequestURI().substring(http.getContextPath().length());
                final Optional<String> app = Stream.of(delegate.prefixes).filter(path::startsWith).findAny();
                if (app.isPresent()) {
                    delegate.service(new HttpServletRequestWrapper(http) { // fake servlet pathInfo and path
                        @Override
                        public String getPathInfo() {
                            return path;
                        }

                        @Override
                        public String getServletPath() {
                            return servletPath;
                        }
                    }, response);
                } else {
                    chain.doFilter(request, response);
                }
            }

            @Override
            public void destroy() {
                delegate.destroy();
            }
        });
        jaxrs.setAsyncSupported(true);
        jaxrs.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.ASYNC), true, builder.getJaxrsMapping());
        ofNullable(builder.getCxfServletParams()).ifPresent(m -> m.forEach(jaxrs::setInitParameter));
    }

    private static class Logs {
        private Logs() {
            // no-op
        }

        private static String forceLength(final String httpMethod, final int l, final boolean right) {
            final String http;
            if (httpMethod == null) { // subresourcelocator implies null http method
                http = "";
            } else {
                http = httpMethod;
            }

            final StringBuilder builder = new StringBuilder();
            if (!right) {
                for (int i = 0; i < l - http.length(); i++) {
                    builder.append(" ");
                }
            }
            builder.append(http);
            if (right) {
                for (int i = 0; i < l - http.length(); i++) {
                    builder.append(" ");
                }
            }
            return builder.toString();
        }

        private static String toSimpleString(final Method mtd) {
            try {
                final StringBuilder sb = new StringBuilder();
                final Type[] typeparms = mtd.getTypeParameters();
                if (typeparms.length > 0) {
                    boolean first = true;
                    sb.append("<");
                    for (Type typeparm : typeparms) {
                        if (!first) {
                            sb.append(",");
                        }
                        sb.append(name(typeparm));
                        first = false;
                    }
                    sb.append("> ");
                }

                final Type genRetType = mtd.getGenericReturnType();
                sb.append(name(genRetType)).append(" ");
                sb.append(mtd.getName()).append("(");
                final Type[] params = mtd.getGenericParameterTypes();
                for (int j = 0; j < params.length; j++) {
                    sb.append(name(params[j]));
                    if (j < (params.length - 1)) {
                        sb.append(", ");
                    }
                }
                sb.append(")");
                final Type[] exceptions = mtd.getGenericExceptionTypes();
                if (exceptions.length > 0) {
                    sb.append(" throws ");
                    for (int k = 0; k < exceptions.length; k++) {
                        sb.append(name(exceptions[k]));
                        if (k < (exceptions.length - 1)) {
                            sb.append(",");
                        }
                    }
                }
                return sb.toString();
            } catch (final Exception e) {
                return "<" + e + ">";
            }
        }

        private static String name(final Type type) {
            if (type instanceof Class<?>) {
                return ((Class) type).getSimpleName().replace("java.lang.", "").replace("java.util", "");
            } else if (type instanceof ParameterizedType) {
                final ParameterizedType pt = (ParameterizedType) type;
                final StringBuilder builder = new StringBuilder();
                builder.append(name(pt.getRawType()));
                final Type[] args = pt.getActualTypeArguments();
                if (args != null) {
                    builder.append("<");
                    for (int i = 0; i < args.length; i++) {
                        builder.append(name(args[i]));
                        if (i < args.length - 1) {
                            builder.append(", ");
                        }
                    }
                    builder.append(">");
                }
                return builder.toString();
            }
            return type.toString();
        }

        private static String singleSlash(final String address, final String value) {
            if (address.endsWith("/") && value.startsWith("/")) {
                return address + value.substring(1);
            }
            if (!address.endsWith("/") && !value.startsWith("/")) {
                return address + '/' + value;
            }
            if ("/".equals(value)) {
                return address;
            }
            return address + value;
        }

        private static class LogOperationEndpointInfo implements Comparable<LogOperationEndpointInfo> {
            private final String http;
            private final String address;
            private final String method;

            private LogOperationEndpointInfo(final String http, final String address, final String method) {
                this.address = address;
                this.method = method;

                if (http != null) {
                    this.http = http;
                } else { // can happen with subresource locators
                    this.http = "";
                }
            }

            @Override
            public int compareTo(final LogOperationEndpointInfo o) {
                int compare = http.compareTo(o.http);
                if (compare != 0) {
                    return compare;
                }

                compare = address.compareTo(o.address);
                if (compare != 0) {
                    return compare;
                }

                return method.compareTo(o.method);
            }
        }

        private static class LogResourceEndpointInfo implements Comparable<LogResourceEndpointInfo> {
            private final String address;
            private final String classname;
            private final List<LogOperationEndpointInfo> operations;
            private final int methodSize;
            private final int methodStrSize;

            private LogResourceEndpointInfo(final String address, final String classname,
                                            final List<LogOperationEndpointInfo> operations,
                                            final int methodSize, final int methodStrSize) {
                this.address = address;
                this.classname = classname;
                this.operations = operations;
                this.methodSize = methodSize;
                this.methodStrSize = methodStrSize;
            }

            @Override
            public int compareTo(final LogResourceEndpointInfo o) {
                final int compare = address.compareTo(o.address);
                if (compare != 0) {
                    return compare;
                }
                return classname.compareTo(o.classname);
            }
        }
    }

    private static class MeecrowaveCXFCdiServlet extends CXFCdiServlet {
        private String[] prefixes;

        @Override
        public void init(final ServletConfig sc) throws ServletException {
            super.init(sc);

            // just logging the endpoints
            final LogFacade log = new LogFacade(CxfCdiAutoSetup.class.getName());
            final String transportId = sc.getInitParameter(TRANSPORT_ID);
            final DestinationRegistry registry = getDestinationRegistryFromBusOrDefault(transportId);
            prefixes = registry.getDestinations().stream()
                    .filter(ServletDestination.class::isInstance)
                    .map(ServletDestination.class::cast)
                    .map(getServletDestinationPath(sc, log))
                    .filter(Objects::nonNull)
                    .toArray(String[]::new);
        }

        private Function<ServletDestination, String> getServletDestinationPath(ServletConfig sc, LogFacade log)
        {
            return sd -> {
                final Endpoint endpoint = ChainInitiationObserver.class.cast(sd.getMessageObserver()).getEndpoint();
                final ApplicationInfo app = ApplicationInfo.class.cast(endpoint.get(Application.class.getName()));
                final JAXRSServiceFactoryBean sfb = JAXRSServiceFactoryBean.class.cast(endpoint.get(JAXRSServiceFactoryBean.class.getName()));
                final String base = sd.getEndpointInfo().getAddress();

                if (sfb != null) {
                    final List<Logs.LogResourceEndpointInfo> resourcesToLog = new ArrayList<>();
                    int classSize = 0;
                    int addressSize = 0;

                    final List<ClassResourceInfo> resources = sfb.getClassResourceInfo();
                    for (final ClassResourceInfo info : resources) {
                        if (info.getResourceClass() == null) { // possible?
                            continue;
                        }

                        final String address = Logs.singleSlash(base, info.getURITemplate().getValue());

                        final String clazz = uproxyName(info.getResourceClass().getName());
                        classSize = Math.max(classSize, clazz.length());
                        addressSize = Math.max(addressSize, address.length());

                        int methodSize = 7;
                        int methodStrSize = 0;

                        final List<Logs.LogOperationEndpointInfo> toLog = new ArrayList<>();

                        final MethodDispatcher md = info.getMethodDispatcher();
                        for (final OperationResourceInfo ori : md.getOperationResourceInfos()) {
                            final String httpMethod = ori.getHttpMethod();
                            final String currentAddress = Logs.singleSlash(address, ori.getURITemplate().getValue());
                            final String methodToStr = Logs.toSimpleString(ori.getMethodToInvoke());
                            toLog.add(new Logs.LogOperationEndpointInfo(httpMethod, currentAddress, methodToStr));

                            if (httpMethod != null) {
                                methodSize = Math.max(methodSize, httpMethod.length());
                            }
                            addressSize = Math.max(addressSize, currentAddress.length());
                            methodStrSize = Math.max(methodStrSize, methodToStr.length());
                        }

                        Collections.sort(toLog);

                        resourcesToLog.add(new Logs.LogResourceEndpointInfo(address, clazz, toLog, methodSize, methodStrSize));
                    }

                    // effective logging
                    log.info("REST Application: " + endpoint.getEndpointInfo().getAddress() + " -> "
                            + ofNullable(app).map(ApplicationInfo::getResourceClass).map(Class::getName).map(CxfCdiAutoSetup::uproxyName).orElse(""));

                    Collections.sort(resourcesToLog);
                    final int fClassSize = classSize;
                    final int fAddressSize = addressSize;
                    resourcesToLog.forEach(resource -> {
                        log.info("     Service URI: "
                                + Logs.forceLength(resource.address, fAddressSize, true) + " -> "
                                + Logs.forceLength(resource.classname, fClassSize, true));

                        resource.operations.forEach(info -> {
                            log.info("          "
                                    + Logs.forceLength(info.http, resource.methodSize, false) + " "
                                    + Logs.forceLength(info.address, fAddressSize, true) + " ->      "
                                    + Logs.forceLength(info.method, resource.methodStrSize, true));
                        });
                        resource.operations.clear();
                    });
                    resourcesToLog.clear();

                    // log @Providers
                    if (Meecrowave.Builder.class.cast(sc.getServletContext().getAttribute("meecrowave.configuration")).isJaxrsLogProviders()) {
                        final ServerProviderFactory spf = ServerProviderFactory.class.cast(endpoint.get(ServerProviderFactory.class.getName()));
                        dump(log, spf, "MessageBodyReaders", "messageReaders");
                        dump(log, spf, "MessageBodyWriters", "messageWriters");
                    }
                } else {
                    final EndpointInfo endpointInfo = endpoint.getEndpointInfo();
                    if (endpointInfo.getName() != null) {
                        log.info("@WebService > " + endpointInfo.getName().toString() + " -> " + base);
                    }
                }

                return base;
            };
        }

        private void dump(final LogFacade log, final ServerProviderFactory spf, final String description, final String fieldName) {
            final Field field = ReflectionUtil.getDeclaredField(ProviderFactory.class, fieldName);
            if (!field.isAccessible()) {
                field.setAccessible(true);
            }
            try {
                final Collection<ProviderInfo<?>> providers = Collection.class.cast(field.get(spf));
                log.info("     " + description);
                providers.stream().map(ProviderInfo::getProvider).forEach(o -> {
                    try {
                        log.info("       - " + o);
                    } catch (final RuntimeException re) {
                        // no-op: maybe cdi context is not active
                    }
                });
            } catch (IllegalAccessException e) {
                // ignore, not that a big deal
            }
        }
    }

    private static String uproxyName(final String clazz) {
        if (clazz.contains("$$")) {
            return clazz.substring(0, clazz.indexOf("$$"));
        }
        return clazz;
    }
}
