/*
 * 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.camel.karaf.maven;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.apache.camel.tooling.util.FileUtil;
import org.apache.camel.tooling.util.PackageHelper;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;

/**
 * Prepares the Karaf provider camel catalog to include component it supports
 */
@Mojo(name = "prepare-catalog-karaf", threadSafe = true)
public class PrepareCatalogKarafMojo extends AbstractMojo {

    /**
     * The maven project.
     */
    @Parameter(property = "project", required = true, readonly = true)
    protected MavenProject project;

    /**
     * The output directory for components catalog
     */
    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/karaf/components")
    protected File componentsOutDir;

    /**
     * The output directory for dataformats catalog
     */
    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/karaf/dataformats")
    protected File dataFormatsOutDir;

    /**
     * The output directory for languages catalog
     */
    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/karaf/languages")
    protected File languagesOutDir;

    /**
     * The output directory for others catalog
     */
    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/karaf/others")
    protected File othersOutDir;

    /**
     * The karaf features directory
     */
    @Parameter(defaultValue = "${project.build.directory}/../../../platforms/karaf/features/src/main/resources/")
    protected File featuresDir;

    /**
     * The components directory where all the Apache Camel components are from the camel-catalog
     */
    @Parameter(defaultValue = "${project.build.directory}/sources/camel-catalog/org/apache/camel/catalog/components")
    protected File componentsDir;

    /**
     * The components directory where there are karaf only components
     */
    @Parameter(defaultValue = "${project.build.directory}/../../../components")
    protected File karafComponentsDir;

    /**
     * The dataformats directory where all the Apache Camel components are from the camel-catalog
     */
    @Parameter(defaultValue = "${project.build.directory}/sources/camel-catalog/org/apache/camel/catalog/dataformats")
    protected File dataformatsDir;

    /**
     * The languages directory where all the Apache Camel components are from the camel-catalog
     */
    @Parameter(defaultValue = "${project.build.directory}/sources/camel-catalog/org/apache/camel/catalog/languages")
    protected File languagessDir;

    /**
     * The languages directory where all the Apache Camel components are from the camel-catalog
     */
    @Parameter(defaultValue = "${project.build.directory}/sources/camel-catalog/org/apache/camel/catalog/others")
    protected File otherssDir;

    /**
     * Maven ProjectHelper.
     */
    @Component
    private MavenProjectHelper projectHelper;

    /**
     * Execute goal.
     *
     * @throws MojoExecutionException execution of the main class or one of the
     *                                threads it generated failed.
     * @throws MojoFailureException   something bad happened...
     */
    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        Set<String> features = findKarafFeatures();
        executeFeatures(features);
    }

    protected void executeFeatures(Set<String> features) throws MojoExecutionException, MojoFailureException {
        // lets use sorted set/maps
        Set<File> jsonFiles = new TreeSet<>();

        if (componentsDir != null && componentsDir.isDirectory()) {
            File[] files = componentsDir.listFiles();
            if (files != null) {
                for (File file : files) {
                    String name = stripExt(file);
                    if (features.contains("camel-" + name) || isCoreComponent(name)) {
                        jsonFiles.add(file);
                    }
                }
            }
        }

        // include paxlogging and eventadmin as regular components
        jsonFiles.add(new File(karafComponentsDir, "camel-eventadmin/target/classes/org/apache/camel/component/eventadmin/eventadmin.json"));
        jsonFiles.add(new File(karafComponentsDir, "camel-paxlogging/target/classes/org/apache/camel/component/paxlogging/paxlogging.json"));

        if (!jsonFiles.isEmpty()) {
            Path outDir = componentsOutDir.toPath();
            copyFiles(outDir, jsonFiles);
            generateJsonList(outDir, "../components.properties");
            getLog().info("Copying " + jsonFiles.size() + " Camel component json descriptors");
        }

        jsonFiles.clear();
        if (dataformatsDir != null && dataformatsDir.isDirectory()) {
            File[] files = dataformatsDir.listFiles();
            if (files != null) {
                for (File file : files) {
                    // all dataformats are supported on karaf
                    jsonFiles.add(file);
                }
            }
        }
        if (!jsonFiles.isEmpty()) {
            Path outDir = dataFormatsOutDir.toPath();
            copyFiles(outDir, jsonFiles);
            generateJsonList(outDir, "../dataformats.properties");
            getLog().info("Copying " + jsonFiles.size() + " Camel dataformat json descriptors");
        }

        jsonFiles.clear();
        if (languagessDir != null && languagessDir.isDirectory()) {
            File[] files = languagessDir.listFiles();
            if (files != null) {
                for (File file : files) {
                    // all languages are supported on karaf
                    jsonFiles.add(file);
                }
            }
        }
        if (!jsonFiles.isEmpty()) {
            Path outDir = languagesOutDir.toPath();
            copyFiles(outDir, jsonFiles);
            generateJsonList(outDir, "../languages.properties");
            getLog().info("Copying " + jsonFiles.size() + " Camel language json descriptors");
        }

        jsonFiles.clear();
        if (otherssDir != null && otherssDir.isDirectory()) {
            File[] files = otherssDir.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (features.contains("camel-" + stripExt(file))) {
                        jsonFiles.add(file);
                    }
                }
            }
        }
        // include others that are in camel-karaf only
        jsonFiles.add(new File(karafComponentsDir, "camel-blueprint/target/classes/blueprint.json"));
        jsonFiles.add(new File(karafComponentsDir, "camel-kura/target/classes/kura.json"));
        jsonFiles.add(new File(karafComponentsDir, "camel-osgi-activator/target/classes/osgi-activator.json"));
        if (!jsonFiles.isEmpty()) {
            Path outDir = othersOutDir.toPath();
            copyFiles(outDir, jsonFiles);
            generateJsonList(outDir, "../others.properties");
            getLog().info("Copying " + jsonFiles.size() + " Camel other json descriptors");
        }
    }

    private static boolean isCoreComponent(String name) {
        return ("bean,browse,controlbus,dataformat,dataset,direct,directvm,file,language,log,mock,ref"
                + ",rest,saga,scheduler,seda,stub,timer,validator,vm,xpath,xslt").contains(name);
    }

    private static String stripExt(File file) {
        String name = file.getName();
        return name.substring(0, name.indexOf("."));
    }

    public static void copyFiles(Path outDir, Collection<File> files) throws MojoFailureException {
        for (File file : files) {
            Path to = outDir.resolve(file.getName());
            try {
                FileUtil.updateFile(file.toPath(), to);
            } catch (IOException e) {
                throw new MojoFailureException("Cannot copy file from " + file + " -> " + to, e);
            }
        }
    }

    public static Set<String> generateJsonList(Path outDir, String outFile) throws MojoFailureException {
        Path all = outDir.resolve(outFile);
        try {
            Set<String> answer = Files.list(outDir).filter(p -> p.getFileName().toString().endsWith(PackageHelper.JSON_SUFIX)).map(p -> p.getFileName().toString())
                    // strip out .json from the name
                    .map(n -> n.substring(0, n.length() - PackageHelper.JSON_SUFIX.length())).sorted().collect(LinkedHashSet::new, LinkedHashSet::add, LinkedHashSet::addAll);
            String data = String.join("\n", answer) + "\n";
            FileUtil.updateFile(all, data);
            return answer;
        } catch (IOException e) {
            throw new MojoFailureException("Error writing to file " + all);
        }
    }

    private Set<String> findKarafFeatures() throws MojoExecutionException, MojoFailureException {
        // load features.xml file and parse it

        Set<String> answer = new LinkedHashSet<>();
        File file = new File(featuresDir, "features.xml");
        try (InputStream is = new FileInputStream(file)) {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
            dbf.setIgnoringComments(true);
            dbf.setIgnoringElementContentWhitespace(true);
            dbf.setNamespaceAware(false);
            dbf.setValidating(false);
            dbf.setXIncludeAware(false);
            dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
            Document dom = dbf.newDocumentBuilder().parse(is);

            NodeList children = dom.getElementsByTagName("features");
            for (int i = 0; i < children.getLength(); i++) {
                Node child = children.item(i);
                if (child.getNodeType() == Node.ELEMENT_NODE) {
                    NodeList children2 = child.getChildNodes();
                    for (int j = 0; j < children2.getLength(); j++) {
                        Node child2 = children2.item(j);
                        if ("feature".equals(child2.getNodeName())) {
                            String artifactId = child2.getAttributes().getNamedItem("name").getTextContent();
                            if (artifactId != null && artifactId.startsWith("camel-")) {
                                answer.add(artifactId);
                            }
                        }
                    }
                }
            }

            getLog().info("Found " + answer.size() + " Camel features in file: " + file);

        } catch (Exception e) {
            throw new MojoExecutionException("Error reading features.xml file", e);
        }

        return answer;
    }

}
