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

import org.apache.meecrowave.Meecrowave;
import org.apache.meecrowave.configuration.Configuration;
import org.apache.meecrowave.logging.tomcat.LogFacade;
import org.apache.tomcat.JarScanFilter;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.corespi.scanner.xbean.CdiArchive;
import org.apache.webbeans.corespi.scanner.xbean.OwbAnnotationFinder;
import org.apache.webbeans.spi.BdaScannerService;
import org.apache.webbeans.spi.BeanArchiveService;
import org.apache.webbeans.util.WebBeansUtil;
import org.apache.webbeans.web.scanner.WebScannerService;
import org.apache.xbean.finder.AnnotationFinder;
import org.apache.xbean.finder.filter.Filter;

import javax.servlet.ServletContext;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Stream;

import static java.util.Optional.of;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toSet;
import static org.apache.tomcat.JarScanType.PLUGGABILITY;

public class OWBTomcatWebScannerService extends WebScannerService {
    private final LogFacade logger = new LogFacade(OWBTomcatWebScannerService.class.getName());
    private final BdaScannerService delegate;
    private final Supplier<OwbAnnotationFinder> finderAccessor;

    protected JarScanFilter filter;
    private String jreBase;

    // just for logging (== temp)
    private final Set<String> urls = new HashSet<>();
    private String docBase;
    private String shared;
    private Consumer<File> fileVisitor;

    public OWBTomcatWebScannerService() {
        this(null, null);
    }


    public OWBTomcatWebScannerService(final BdaScannerService delegate, final Supplier<OwbAnnotationFinder> finderAccessor) {
        this.delegate = delegate;
        this.finderAccessor = finderAccessor;
    }

    @Override
    public void init(final Object context) {
        if (delegate != null) {
            delegate.init(context);
        }
    }

    @Override
    public OwbAnnotationFinder getFinder() {
        if (finderAccessor != null) {
            return finderAccessor.get();
        }
        return super.getFinder();
    }

    @Override
    public Map<BeanArchiveService.BeanArchiveInformation, Set<Class<?>>> getBeanClassesPerBda() {
        if (delegate != null) {
            return delegate.getBeanClassesPerBda();
        }
        return super.getBeanClassesPerBda();
    }

    @Override
    public void release() {
        if (delegate != null) {
            delegate.release();
        } else {
            super.release();
        }
    }

    @Override
    public Set<Class<?>> getBeanClasses() {
        if (delegate != null) {
            return delegate.getBeanClasses();
        }
        return super.getBeanClasses();
    }

    @Override
    public void scan() {
        if (delegate != null) {
            if (getFinder() == null) {
                delegate.scan();
            }
            if (finder == null) {
                finder = getFinder();
            }
        }

        if (finder != null) {
            return;
        }

        super.scan();
        scanGroovy(WebBeansUtil.getCurrentClassLoader());
        if (!urls.isEmpty()) {
            logger.info("OpenWebBeans scanning:");
            final String m2 = new File(System.getProperty("user.home", "."), ".m2/repository").getAbsolutePath();
            final String base = ofNullable(docBase).orElse("$$$");
            final String sharedBase = ofNullable(shared).orElse("$$$");
            final String runnerBase = ofNullable(System.getProperty("meecrowave.base")).orElse("$$$");
            final String runnerHome = ofNullable(System.getProperty("meecrowave.home")).orElse("$$$");
            urls.stream().map(u -> {
                String shownValue = u
                        // protocol
                        .replace("file://", "")
                        .replace("file:", "")
                        .replace("jar:", "")
                        // URL suffix
                        .replace("!/META-INF/beans.xml", "")
                        .replace("!/", "")
                        // beans.xml
                        .replace("META-INF/beans.xml", "");

                // try to make it shorter
                if (shownValue.startsWith(m2)) {
                    shownValue = "${maven}/" + shownValue.substring(shownValue.replace(File.separatorChar, '/').lastIndexOf('/') + 1);
                } else if (shownValue.startsWith(base)) {
                    shownValue = "${app}" + shownValue.replace(base, "");
                } else if (shownValue.startsWith(sharedBase)) {
                    shownValue = "${shared}" + shownValue.replace(sharedBase, "");
                } else if (shownValue.startsWith(runnerBase)) {
                    shownValue = "${base}" + shownValue.replace(runnerBase, "");
                } else if (shownValue.startsWith(runnerHome)) {
                    shownValue = "${home}" + shownValue.replace(runnerHome, "");
                }

                return shownValue;
            }).sorted().forEach(v -> logger.info("    " + v));

            if (fileVisitor != null) {
                urls.stream()
                        .filter(this::isFile)
                        .map(this::toFile)
                        .filter(File::isDirectory)
                        .forEach(fileVisitor);
            }
        }
        urls.clear(); // no more needed
        filter = null;
        docBase = null;
        shared = null;
    }

    private File toFile(final String url) {
        try {
            return new File(new URL(url).getFile());
        } catch (final MalformedURLException e) {
            return new File(url.substring("file://".length(), url.length()));
        }
    }

    private boolean isFile(final String url) {
        return url.startsWith("file:") && !url.endsWith("!/") && !url.endsWith("!/META-INF/beans.xml");
    }

    private void scanGroovy(final ClassLoader currentClassLoader) {
        if (currentClassLoader == null || !currentClassLoader.getClass().getName().equals("groovy.lang.GroovyClassLoader")) {
            return;
        }
        try {
            final Class<?>[] getLoadedClasses = Class[].class.cast(
                    currentClassLoader.getClass()
                            .getMethod("getLoadedClasses")
                            .invoke(currentClassLoader));
            addClassesToDefault(getLoadedClasses);
        } catch (final Exception e) {
            new LogFacade(OWBTomcatWebScannerService.class.getName()).warn(e.getMessage());
        }
    }

    private void addClassesToDefault(final Class<?>[] all) throws Exception {
        if (all == null || all.length == 0) {
            return;
        }

        final Field linking = AnnotationFinder.class.getDeclaredField("linking");
        final Method readClassDef = AnnotationFinder.class.getDeclaredMethod("readClassDef", Class.class);
        if (!readClassDef.isAccessible()) {
            readClassDef.setAccessible(true);
        }
        if (!linking.isAccessible()) {
            linking.setAccessible(true);
        }

        final URI uri = URI.create("jar:file://!/"); // we'll never find it during scanning and it avoids to create a custom handler
        final URL url = uri.toURL();
        final String key = uri.toASCIIString();
        CdiArchive.FoundClasses foundClasses = archive.classesByUrl().get(key);
        if (foundClasses == null) {
            final BeanArchiveService beanArchiveService = webBeansContext().getBeanArchiveService();
            foundClasses = CdiArchive.FoundClasses.class.cast(
                    CdiArchive.FoundClasses.class.getConstructor(CdiArchive.class, URL.class, Collection.class, BeanArchiveService.BeanArchiveInformation.class)
                            .newInstance(null, url, new HashSet<>(), beanArchiveService.getBeanArchiveInformation(url)));
            archive.classesByUrl().put(key, foundClasses);
        }

        foundClasses.getClassNames().addAll(Stream.of(all).map(Class::getName).collect(toSet()));

        try {
            linking.set(finder, true);

            Stream.of(all).forEach(c -> { // populate classInfos map to support annotated mode which relies on ClassInfo
                try {
                    readClassDef.invoke(finder, c);
                } catch (final IllegalAccessException e) {
                    throw new IllegalStateException(e);
                } catch (final InvocationTargetException e) {
                    throw new IllegalStateException(e.getCause());
                }
            });
        } finally {
            try {
                linking.set(finder, false);
            } catch (final IllegalAccessException e) {
                // no-op
            }
        }
    }

    @Override
    protected void filterExcludedJars(final Set<URL> classPathUrls) {
        String jreBaseTmp;
        try {
            jreBaseTmp = new File(System.getProperty("java.home")).toURI().toURL().toExternalForm();
        } catch (MalformedURLException e) {
            jreBaseTmp = System.getProperty("java.home");
        }
        jreBase = jreBaseTmp;

        super.filterExcludedJars(classPathUrls);
    }

    @Override
    protected int isExcludedJar(final String path) {
        if (path.startsWith(jreBase) || (path.startsWith("jar:") && path.indexOf(jreBase) == 4)) {
            return jreBase.length();
        }

        // jar:file:spring-boot-cdi-launcher-1.0-SNAPSHOT.jar!/BOOT-INF/lib/x.jar!/
        if (path.startsWith("jar:file:") && path.endsWith(".jar!/")) {
            final int lastSep = path.substring(0, path.length() - 2).lastIndexOf('/');
            if (lastSep > 0) {
                return filter != null && filter.check(PLUGGABILITY, path.substring(lastSep + 1, path.length() - 2)) ?
                        -1 : (path.indexOf(".jar") - 1 /*should be lastIndexOf but filterExcludedJar logic would be broken*/);
            }
        }

        final int filenameIdx = path.replace(File.separatorChar, '/').replace("!/", "").lastIndexOf('/') + 1;
        if (filenameIdx < 0 || filenameIdx >= path.length()) { // unlikely
            return -1;
        }

        return filter!= null && filter.check(PLUGGABILITY, path.substring(filenameIdx)) ? -1 : (path.indexOf(".jar") - 1);
    }

    // replace init
    public void setFilter(final JarScanFilter filter, final ServletContext ctx) {
        this.filter = filter;

        super.init(ctx);
        final Configuration config = Configuration.class.cast(ServletContext.class.cast(ctx).getAttribute("meecrowave.configuration"));
        if (this.filter == null) {
            this.filter = new KnownJarsFilter(config);
        }

        final Filter userFilter = webBeansContext().getService(Filter.class);
        if (KnownClassesFilter.class.isInstance(userFilter)) {
            KnownClassesFilter.class.cast(userFilter).init(config);
        }
    }

    @Override
    protected void addWebBeansXmlLocation(final URL beanArchiveUrl) {
        final String url = beanArchiveUrl.toExternalForm();
        if (urls.add(of(url)
                .map(s -> s.startsWith("jar:") && s.endsWith("!/META-INF/beans.xml") ? s.substring("jar:".length(), s.length() - "!/META-INF/beans.xml".length()) : s)
                .get())) {
            super.doAddWebBeansXmlLocation(beanArchiveUrl);
        }
    }

    public void setShared(final String shared) {
        this.shared = ofNullable(shared).map(File::new).filter(File::isDirectory).map(File::getAbsolutePath).orElse(null);
    }

    public void setDocBase(final String docBase) {
        this.docBase = docBase;
    }

    public void setFileVisitor(final Consumer<File> fileVisitor) {
        this.fileVisitor = fileVisitor;
    }

    //don't rename this method - in case of owb2 it overrides the method defined in AbstractMetaDataDiscovery
    protected WebBeansContext webBeansContext() {
        return WebBeansContext.getInstance(); //only way to be compatible with owb 1.7.x and 2.x (without reflection)
    }
}
