/*
 * Copyright 2016-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.onosjar;

import com.facebook.buck.cli.BuckConfig;
import com.facebook.buck.jvm.java.CalculateAbi;
import com.facebook.buck.jvm.java.DefaultJavaLibrary;
import com.facebook.buck.jvm.java.JavaBuckConfig;
import com.facebook.buck.jvm.java.JavaLibrary;
import com.facebook.buck.jvm.java.JavaLibraryDescription;
import com.facebook.buck.jvm.java.JavaOptions;
import com.facebook.buck.jvm.java.JavaSourceJar;
import com.facebook.buck.jvm.java.JavacOptions;
import com.facebook.buck.jvm.java.JavacOptionsAmender;
import com.facebook.buck.jvm.java.JavacOptionsFactory;
import com.facebook.buck.jvm.java.JavacToJarStepFactory;
import com.facebook.buck.jvm.java.JavadocJar;
import com.facebook.buck.jvm.java.MavenUberJar;
import com.facebook.buck.maven.AetherUtil;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.Flavor;
import com.facebook.buck.model.Flavored;
import com.facebook.buck.model.ImmutableFlavor;
import com.facebook.buck.parser.NoSuchBuildTargetException;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.BuildRules;
import com.facebook.buck.rules.BuildTargetSourcePath;
import com.facebook.buck.rules.Description;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.SourcePaths;
import com.facebook.buck.rules.TargetGraph;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

import java.nio.file.Path;
import java.util.List;

import static com.facebook.buck.jvm.common.ResourceValidator.validateResources;

/**
 * Description for the onos_jar rules.
 *
 * Currently, this only does Swagger generation.
 */
public class OnosJarDescription implements Description<OnosJarDescription.Arg>, Flavored {
    public static final BuildRuleType TYPE = BuildRuleType.of("onos_jar");
    public static final Flavor NON_OSGI_JAR = ImmutableFlavor.of("non-osgi");

    public static final ImmutableSet<Flavor> SUPPORTED_FLAVORS = ImmutableSet.of(
            JavaLibrary.SRC_JAR,
            JavaLibrary.MAVEN_JAR,
            JavaLibrary.JAVADOC_JAR,
            NON_OSGI_JAR);

    private final JavacOptions defaultJavacOptions;
    private final JavaOptions defaultJavaOptions;

    public OnosJarDescription(BuckConfig config) {
        JavaBuckConfig javaConfig = new JavaBuckConfig(config);
        defaultJavacOptions = javaConfig.getDefaultJavacOptions();
        defaultJavaOptions = javaConfig.getDefaultJavaOptions();
    }

    @Override
    public BuildRuleType getBuildRuleType() {
        return TYPE;
    }

    @Override
    public Arg createUnpopulatedConstructorArg() {
        return new Arg();
    }

    @Override
    public <A extends Arg> BuildRule createBuildRule(TargetGraph targetGraph,
                                                     BuildRuleParams params,
                                                     BuildRuleResolver resolver,
                                                     A args)
            throws NoSuchBuildTargetException {


        SourcePathResolver pathResolver = new SourcePathResolver(resolver);
        BuildTarget target = params.getBuildTarget();

        // We know that the flavour we're being asked to create is valid, since the check is done when
        // creating the action graph from the target graph.

        ImmutableSortedSet<Flavor> flavors = target.getFlavors();
        BuildRuleParams paramsWithMavenFlavor = null;

        if (flavors.contains(JavaLibrary.MAVEN_JAR)) {
            paramsWithMavenFlavor = params;

            // Maven rules will depend upon their vanilla versions, so the latter have to be constructed
            // without the maven flavor to prevent output-path conflict
            params = params.copyWithBuildTarget(
                    params.getBuildTarget().withoutFlavors(ImmutableSet.of(JavaLibrary.MAVEN_JAR)));
        }

        if (flavors.contains(JavaLibrary.SRC_JAR)) {
            args.mavenCoords = args.mavenCoords.transform(
                    new Function<String, String>() {
                        @Override
                        public String apply(String input) {
                            return AetherUtil.addClassifier(input, AetherUtil.CLASSIFIER_SOURCES);
                        }
                    });

            if (!flavors.contains(JavaLibrary.MAVEN_JAR)) {
                return new JavaSourceJar(
                        params,
                        pathResolver,
                        args.srcs.get(),
                        args.mavenCoords);
            } else {
                return MavenUberJar.SourceJar.create(
                        Preconditions.checkNotNull(paramsWithMavenFlavor),
                        pathResolver,
                        args.srcs.get(),
                        args.mavenCoords,
                        Optional.absent()); //FIXME
            }
        }

        if (flavors.contains(JavaLibrary.JAVADOC_JAR)) {
            args.mavenCoords = args.mavenCoords.transform(
                    new Function<String, String>() {
                        @Override
                        public String apply(String input) {
                            return AetherUtil.addClassifier(input, AetherUtil.CLASSIFIER_JAVADOC);
                        }
                    });

            JavadocJar.JavadocArgs.Builder javadocArgs = JavadocJar.JavadocArgs.builder()
                    .addArg("-windowtitle", target.getShortName())
                    .addArg("-link", "http://docs.oracle.com/javase/8/docs/api")
                    .addArg("-tag", "onos.rsModel:a:\"onos model\""); //FIXME from buckconfig + rule

            final ImmutableSortedMap.Builder<SourcePath, Path> javadocFiles = ImmutableSortedMap.naturalOrder();
            if (args.javadocFiles.isPresent()) {
                for (SourcePath path : args.javadocFiles.get()) {
                    javadocFiles.put(path,
                                     JavadocJar.getDocfileWithPath(pathResolver, path, args.javadocFilesRoot.orNull()));
                }
            }


            if (!flavors.contains(JavaLibrary.MAVEN_JAR)) {
                return new JavadocJar(
                        params,
                        pathResolver,
                        args.srcs.get(),
                        javadocFiles.build(),
                        javadocArgs.build(),
                        args.mavenCoords);
            } else {
                return MavenUberJar.MavenJavadocJar.create(
                        Preconditions.checkNotNull(paramsWithMavenFlavor),
                        pathResolver,
                        args.srcs.get(),
                        javadocFiles.build(),
                        javadocArgs.build(),
                        args.mavenCoords,
                        Optional.absent()); //FIXME
            }
        }

        JavacOptions javacOptions = JavacOptionsFactory.create(
                defaultJavacOptions,
                params,
                resolver,
                pathResolver,
                args
        );

        BuildTarget abiJarTarget = params.getBuildTarget().withAppendedFlavors(CalculateAbi.FLAVOR);

        ImmutableSortedSet<BuildRule> exportedDeps = resolver.getAllRules(args.exportedDeps.get());

        // Build the resources string
        List<String> resourceMappings = Lists.newArrayList();

        if (args.includeResources.isPresent()) {
            args.includeResources.get().entrySet().forEach(p ->
                resourceMappings.add(String.format("%s=%s", p.getKey(), p.getValue())));
        }

        if (args.apiTitle.isPresent()) {
            resourceMappings.add("WEB-INF/classes/apidoc/swagger.json=swagger.json");
        }

        Optional<String> includedResourcesString = Optional.of(String.join(",", resourceMappings));
        final DefaultJavaLibrary defaultJavaLibrary;
        if (!flavors.contains(NON_OSGI_JAR)) {
            defaultJavaLibrary =
                    resolver.addToIndex(
                            new OnosJar(
                                    params.appendExtraDeps(
                                            Iterables.concat(
                                                    BuildRules.getExportedRules(
                                                            Iterables.concat(
                                                                    params.getDeclaredDeps().get(),
                                                                    exportedDeps,
                                                                    resolver.getAllRules(args.providedDeps.get()))),
                                                    pathResolver.filterBuildRuleInputs(
                                                            javacOptions.getInputs(pathResolver)))),
                                    pathResolver,
                                    args.srcs.get(),
                                    validateResources(
                                            pathResolver,
                                            params.getProjectFilesystem(),
                                            args.resources.get()),
                                    javacOptions.getGeneratedSourceFolderName(),
                                    args.proguardConfig.transform(
                                            SourcePaths.toSourcePath(params.getProjectFilesystem())),
                                    args.postprocessClassesCommands.get(), // FIXME this should be forbidden
                                    exportedDeps,
                                    resolver.getAllRules(args.providedDeps.get()),
                                    new BuildTargetSourcePath(abiJarTarget),
                                    javacOptions.trackClassUsage(),
                                /* additionalClasspathEntries */ ImmutableSet.<Path>of(),
                                    new OnosJarStepFactory(javacOptions, JavacOptionsAmender.IDENTITY,
                                                           args.webContext, args.apiTitle, args.apiVersion,
                                                           args.apiPackage, args.apiDescription, args.resources,
                                                           args.groupId, args.bundleName, args.bundleVersion,
                                                           args.bundleLicense, args.bundleDescription, args.importPackages,
                                                           args.exportPackages, includedResourcesString,
                                                           args.dynamicimportPackages, args.privatePackages, args.embeddedDependencies, args.bundleClasspath),
                                    args.resourcesRoot,
                                    args.manifestFile,
                                    args.mavenCoords,
                                    args.tests.get(),
                                    javacOptions.getClassesToRemoveFromJar(),
                                    args.webContext,
                                    args.apiTitle,
                                    args.apiVersion,
                                    args.apiPackage,
                                    args.apiDescription,
                                    args.includeResources));
        } else {
            defaultJavaLibrary =
                    resolver.addToIndex(
                            new DefaultJavaLibrary(
                                    params.appendExtraDeps(
                                            Iterables.concat(
                                                    BuildRules.getExportedRules(
                                                            Iterables.concat(
                                                                    params.getDeclaredDeps().get(),
                                                                    exportedDeps,
                                                                    resolver.getAllRules(args.providedDeps.get()))),
                                                    pathResolver.filterBuildRuleInputs(
                                                            javacOptions.getInputs(pathResolver)))),
                                    pathResolver,
                                    args.srcs.get(),
                                    validateResources(
                                            pathResolver,
                                            params.getProjectFilesystem(),
                                            args.resources.get()),
                                    javacOptions.getGeneratedSourceFolderName(),
                                    args.proguardConfig.transform(
                                            SourcePaths.toSourcePath(params.getProjectFilesystem())),
                                    args.postprocessClassesCommands.get(),
                                    exportedDeps,
                                    resolver.getAllRules(args.providedDeps.get()),
                                    new BuildTargetSourcePath(abiJarTarget),
                                    javacOptions.trackClassUsage(),
                                    /* additionalClasspathEntries */ ImmutableSet.<Path>of(),
                                    new JavacToJarStepFactory(javacOptions, JavacOptionsAmender.IDENTITY),
                                    args.resourcesRoot,
                                    args.manifestFile,
                                    args.mavenCoords,
                                    args.tests.get(),
                                    javacOptions.getClassesToRemoveFromJar()));
        }

        resolver.addToIndex(
                CalculateAbi.of(
                        abiJarTarget,
                        pathResolver,
                        params,
                        new BuildTargetSourcePath(defaultJavaLibrary.getBuildTarget())));

        return defaultJavaLibrary;
    }

    @Override
    public boolean hasFlavors(ImmutableSet<Flavor> flavors) {
        return SUPPORTED_FLAVORS.containsAll(flavors);
    }

    public static class Arg extends JavaLibraryDescription.Arg {
        public Optional<String> webContext;
        public Optional<String> apiTitle;
        public Optional<String> apiVersion;
        public Optional<String> apiPackage;
        public Optional<String> apiDescription;

        public Optional<String> groupId;
        public Optional<String> bundleName;
        public Optional<String> bundleVersion;
        public Optional<String> bundleLicense;
        public Optional<String> bundleDescription;

        public Optional<String> importPackages;
        public Optional<String> privatePackages;
        public Optional<String> exportPackages;
        public Optional<ImmutableSortedMap<String, SourcePath>> includeResources;
        public Optional<String> dynamicimportPackages;
        public Optional<String> embeddedDependencies;
        public Optional<String> bundleClasspath;
    }
}