/*
 * 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.sling.maven.bundlesupport;

import static org.objectweb.asm.ClassReader.SKIP_CODE;
import static org.objectweb.asm.ClassReader.SKIP_DEBUG;
import static org.objectweb.asm.ClassReader.SKIP_FRAMES;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.json.Json;
import javax.json.JsonException;
import javax.json.JsonWriter;

import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.apache.sling.adapter.annotations.Adaptable;
import org.apache.sling.adapter.annotations.Adaptables;
import org.codehaus.plexus.util.StringUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.scannotation.AnnotationDB;

/**
 * Build  <a href="http://sling.apache.org/documentation/the-sling-engine/adapters.html">adapter metadata (JSON)</a> for the Web Console Plugin at {@code /system/console/status-adapters} and
 * {@code /system/console/adapters} from classes annotated with
 * <a href="https://github.com/apache/sling-adapter-annotations">adapter annotations</a>.
 */
@Mojo(name="generate-adapter-metadata", defaultPhase = LifecyclePhase.PROCESS_CLASSES,
    threadSafe = true, requiresDependencyResolution = ResolutionScope.COMPILE)
public class GenerateAdapterMetadataMojo extends AbstractMojo {

    private static final String ADAPTABLE_DESC = "L" + Adaptable.class.getName().replace('.', '/') + ";";

    private static final String ADAPTABLES_DESC = "L" + Adaptables.class.getName().replace('.', '/') + ";";

    private static final String DEFAULT_CONDITION = "If the adaptable is a %s.";

    private static String getSimpleName(final ClassNode clazz) {
        final String internalName = clazz.name;
        final int idx = internalName.lastIndexOf('/');
        if (idx == -1) {
            return internalName;
        } else {
            return internalName.substring(idx + 1);
        }
    }

    /** The directory which to check for classes with adapter metadata annotations. */
    @Parameter(defaultValue = "${project.build.outputDirectory}")
    private File buildOutputDirectory;

    /**
     * Name of the generated descriptor file.
     */
    @Parameter(property = "adapter.descriptor.name", defaultValue = "SLING-INF/adapters.json")
    private String fileName;

    /**
     * The output directory in which to emit the descriptor file with name {@link GenerateAdapterMetadataMojo#fileName}.
     */
    @Parameter(defaultValue = "${project.build.outputDirectory}", required = true)
    private File outputDirectory;

    /**
     * The Maven project.
     */
    @Parameter( defaultValue = "${project}", readonly = true )
    private MavenProject project;

    public void execute() throws MojoExecutionException, MojoFailureException {
        try {
            final Map<String,Object> descriptor = new HashMap<>();

            final AnnotationDB annotationDb = new AnnotationDB();
            annotationDb.scanArchives(buildOutputDirectory.toURI().toURL());

            final Set<String> annotatedClassNames = new HashSet<>();
            addAnnotatedClasses(annotationDb, annotatedClassNames, Adaptable.class);
            addAnnotatedClasses(annotationDb, annotatedClassNames, Adaptables.class);

            for (final String annotatedClassName : annotatedClassNames) {
                getLog().info(String.format("found adaptable annotation on %s", annotatedClassName));
                final String pathToClassFile = annotatedClassName.replace('.', '/') + ".class";
                final File classFile = new File(buildOutputDirectory, pathToClassFile);
                final FileInputStream input = new FileInputStream(classFile);
                final ClassReader classReader;
                try {
                    classReader = new ClassReader(input);
                } finally {
                    input.close();
                }
                final ClassNode classNode = new ClassNode();
                classReader.accept(classNode, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES);

                final List<AnnotationNode> annotations = classNode.invisibleAnnotations;
                for (final AnnotationNode annotation : annotations) {
                    if (ADAPTABLE_DESC.equals(annotation.desc)) {
                        parseAdaptableAnnotation(annotation, classNode, descriptor);
                    } else if (ADAPTABLES_DESC.equals(annotation.desc)) {
                        parseAdaptablesAnnotation(annotation, classNode, descriptor);
                    }
                }

            }

            final File outputFile = new File(outputDirectory, fileName);
            outputFile.getParentFile().mkdirs();
            try (FileWriter writer = new FileWriter(outputFile);
                    JsonWriter jsonWriter = Json.createWriter(writer)) {
                jsonWriter.writeObject(JsonSupport.toJson(descriptor));
            }
            addResource();

        } catch (IOException e) {
            throw new MojoExecutionException("Unable to generate metadata", e);
        } catch (JsonException e) {
            throw new MojoExecutionException("Unable to generate metadata", e);
        }

    }

    private void addAnnotatedClasses(final AnnotationDB annotationDb, final Set<String> annotatedClassNames, final Class<? extends Annotation> clazz) {
        Set<String> classNames = annotationDb.getAnnotationIndex().get(clazz.getName());
        if (classNames == null || classNames.isEmpty()) {
            getLog().debug("No classes found with adaptable annotations.");
        } else {
            annotatedClassNames.addAll(classNames);
        }
    }

    private void addResource() {
        final String ourRsrcPath = this.outputDirectory.getAbsolutePath();
        boolean found = false;
        final Iterator<Resource> rsrcIterator = this.project.getResources().iterator();
        while (!found && rsrcIterator.hasNext()) {
            final Resource rsrc = rsrcIterator.next();
            found = rsrc.getDirectory().equals(ourRsrcPath);
        }
        if (!found) {
            final Resource resource = new Resource();
            resource.setDirectory(this.outputDirectory.getAbsolutePath());
            this.project.addResource(resource);
        }

    }

    private void parseAdaptablesAnnotation(final AnnotationNode annotation, final ClassNode classNode,
            final Map<String,Object> descriptor) throws JsonException {
        final Iterator<?> it = annotation.values.iterator();
        while (it.hasNext()) {
            Object name = it.next();
            Object value = it.next();
            if ("value".equals(name)) {
                @SuppressWarnings("unchecked")
                final List<AnnotationNode> annotations = (List<AnnotationNode>) value;
                for (final AnnotationNode innerAnnotation : annotations) {
                    if (ADAPTABLE_DESC.equals(innerAnnotation.desc)) {
                        parseAdaptableAnnotation(innerAnnotation, classNode, descriptor);
                    }
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void parseAdaptableAnnotation(final AnnotationNode annotation, final ClassNode annotatedClass,
            final Map<String,Object> descriptor) throws JsonException {
        String adaptableClassName = null;
        List<AnnotationNode> adapters = null;

        final List<?> values = annotation.values;

        final Iterator<?> it = values.iterator();
        while (it.hasNext()) {
            Object name = it.next();
            Object value = it.next();

            if ("adaptableClass".equals(name)) {
                adaptableClassName = ((Type) value).getClassName();
            } else if ("adapters".equals(name)) {
                adapters = (List<AnnotationNode>) value;
            }
        }

        if (adaptableClassName == null || adapters == null) {
            throw new IllegalArgumentException(
                    "Adaptable annotation is malformed. Expecting a classname and a list of adapter annotation.");
        }

        Map<String,Object> adaptableDescription;
        if (descriptor.containsKey(adaptableClassName)) {
            adaptableDescription = (Map<String,Object>)descriptor.get(adaptableClassName);
        } else {
            adaptableDescription = new HashMap<>();
            descriptor.put(adaptableClassName, adaptableDescription);
        }

        for (final AnnotationNode adapter : adapters) {
            parseAdapterAnnotation(adapter, annotatedClass, adaptableDescription);
        }
    }

    @SuppressWarnings("unchecked")
    private void parseAdapterAnnotation(final AnnotationNode annotation, final ClassNode annotatedClass,
            final Map<String,Object> adaptableDescription) throws JsonException {
        String condition = null;
        List<Type> adapterClasses = null;

        final List<?> values = annotation.values;

        final Iterator<?> it = values.iterator();
        while (it.hasNext()) {
            final Object name = it.next();
            final Object value = it.next();

            if (StringUtils.isEmpty(condition)) {
                condition = String.format(DEFAULT_CONDITION, getSimpleName(annotatedClass));
            }

            if ("condition".equals(name)) {
                condition = (String) value;
            } else if ("value".equals(name)) {
                adapterClasses = (List<Type>) value;
            }
        }

        if (adapterClasses == null) {
            throw new IllegalArgumentException("Adapter annotation is malformed. Expecting a list of adapter classes");
        }

        for (final Type adapterClass : adapterClasses) {
            JsonSupport.accumulate(adaptableDescription, condition, adapterClass.getClassName());
        }
    }

}
