/*
 * Copyright 2015-present Open Networking Foundation
 *
 * Licensed 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.onosproject.maven;

import com.google.common.collect.Maps;
import com.thoughtworks.qdox.JavaProjectBuilder;
import com.thoughtworks.qdox.model.JavaAnnotation;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaField;
import com.thoughtworks.qdox.model.expression.Add;
import com.thoughtworks.qdox.model.expression.AnnotationValue;
import com.thoughtworks.qdox.model.expression.AnnotationValueList;
import com.thoughtworks.qdox.model.expression.FieldRef;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.jar.JarEntry;

/**
 * Produces ONOS component configuration catalogue resources.
 */
@Mojo(name = "cfg", defaultPhase = LifecyclePhase.GENERATE_RESOURCES)
@java.lang.SuppressWarnings("squid:S1148")
public class OnosCfgMojo extends AbstractMojo {

    /**
     * The directory where the generated catalogue file will be put.
     */
    @Parameter(defaultValue = "${basedir}")
    protected File srcDirectory;

    /**
     * The directory where the generated catalogue file will be put.
     */
    @Parameter(defaultValue = "${project.build.outputDirectory}")
    protected File dstDirectory;

    @Override
    public void execute() throws MojoExecutionException {
        getLog().info("Generating ONOS component configuration catalogues...");
        try {
            CfgDefGenerator gen = new CfgDefGenerator(dstDirectory, srcDirectory);
            gen.analyze();
            gen.generate();
        } catch (Exception e) {
            e.printStackTrace();
            throw new MojoExecutionException("Unable to generate property catalog", e);
        }
    }


    private class CfgDefGenerator {

        private static final String COMPONENT = "org.osgi.service.component.annotations.Component";
        private static final String PROPERTY = "property";
        private static final String SEP = "|";
        private static final String UTF_8 = "UTF-8";
        private static final String JAVA = ".java";
        private static final String EXT = ".cfgdef";
        private static final String STRING = "STRING";
        private static final String NO_DESCRIPTION = "no description provided";

        private final File dstDir;
        private final JavaProjectBuilder builder;

        private final Map<String, String> constants = Maps.newHashMap();


        private CfgDefGenerator(File dstDir, File srcDir) {
            this.dstDir = dstDir;
            this.builder = new JavaProjectBuilder();
            builder.addSourceTree(new File(srcDir, "src/main/java"));

//            Arrays.stream(sourceFilePaths).forEach(filename -> {
//                try {
//                    if (filename.endsWith(JAVA))
//                        builder.addSource(new File(filename));
//                } catch (ParseException e) {
//                    // When unable to parse, skip the source; leave it to javac to fail.
//                } catch (IOException e) {
//                    throw new IllegalArgumentException("Unable to open file", e);
//                }
//            });
        }

        public void analyze() {
            builder.getClasses().forEach(this::collectConstants);
        }

        private void collectConstants(JavaClass javaClass) {
            javaClass.getFields().stream()
                    .filter(f -> f.isStatic() && f.isFinal() && !f.isPrivate())
                    .forEach(f -> constants.put(f.getName(), f.getInitializationExpression()));
        }

        public void generate() throws IOException {
            for (JavaClass javaClass : builder.getClasses()) {
                processClass(javaClass);
            }
        }

        private void processClass(JavaClass javaClass) throws IOException {
            Optional<JavaAnnotation> annotation = javaClass.getAnnotations().stream()
                    .filter(ja -> ja.getType().getName().equals(COMPONENT))
                    .findFirst();
            if (annotation.isPresent()) {
                AnnotationValue property = annotation.get().getProperty(PROPERTY);
                List<String> lines = new ArrayList<>();
                if (property instanceof AnnotationValueList) {
                    AnnotationValueList list = (AnnotationValueList) property;
                    list.getValueList().forEach(v -> processProperty(lines, javaClass, v));
                } else {
                    processProperty(lines, javaClass, property);
                }

                if (!lines.isEmpty()) {
                    writeCatalog(javaClass, lines);
                }
            }
        }

        private void processProperty(List<String> lines, JavaClass javaClass,
                                     AnnotationValue value) {
            String s = elaborate(value);
            String[] pex = s.split("=", 2);

            if (pex.length == 2) {
                String[] rex = pex[0].split(":", 2);
                String name = rex[0];
                String type = rex.length == 2 ? rex[1].toUpperCase() : STRING;
                String def = pex[1];
                String desc = description(javaClass, name);

                if (desc != null) {
                    String line = name + SEP + type + SEP + def + SEP + desc;
                    getLog().info("Processing property " + line + " ...");
                    lines.add(line + "\n");
                }
            }
        }

        // Retrieve description from a comment preceding the field named the same
        // as the property or
        // TODO: from an annotated comment.
        private String description(JavaClass javaClass, String name) {
            if (name.startsWith("_")) {
                // Static property - just leave it as is, not for inclusion in the cfg defs
                return null;
            }
            JavaField field = javaClass.getFieldByName(name);
            if (field != null) {
                String comment = field.getComment();
                return comment != null ? comment : NO_DESCRIPTION;
            }
            throw new IllegalStateException("cfgdef could not find a variable named " + name + " in " + javaClass.getName());
        }

        private String elaborate(AnnotationValue value) {
            if (value instanceof Add) {
                return elaborate(((Add) value).getLeft()) + elaborate(((Add) value).getRight());
            } else if (value instanceof FieldRef) {
                return elaborate((FieldRef) value);
            } else if (value != null) {
                return stripped(value.toString());
            } else {
                return "";
            }
        }

        private String elaborate(FieldRef field) {
            String name = field.getName();
            String value = constants.get(name);
            if (value != null) {
                return stripped(value);
            }
            throw new IllegalStateException("Constant " + name + " cannot be elaborated;" +
                                                    " value not in the same compilation context");
        }

        private String stripped(String s) {
            return s.trim().replaceFirst("^[^\"]*\"", "").replaceFirst("\"$", "");
        }

        private void writeCatalog(JavaClass javaClass, List<String> lines) {
            File dir = new File(dstDir, javaClass.getPackageName().replace('.', '/'));
            dir.mkdirs();

            File cfgDef = new File(dir, javaClass.getName().replace('.', '/') + ".cfgdef");
            try (FileWriter fw = new FileWriter(cfgDef);
                 PrintWriter pw = new PrintWriter(fw)) {
                pw.println("# This file is auto-generated by onos-maven-plugin");
                lines.forEach(pw::println);
            } catch (IOException e) {
                System.err.println("Unable to write catalog for " + javaClass.getName());
                e.printStackTrace();
            }
        }

    }
}