/*
 * 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.feature.maven.mojos.apis;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;

import org.apache.felix.utils.manifest.Clause;
import org.apache.maven.model.License;
import org.apache.maven.model.Model;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.apache.sling.feature.Artifact;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Feature;

/**
 * Context for creating the api jars
 */
public class ApisJarContext {

    /**
     * Information about a single artifact (bundle) taking part in the api generation.
     */
    public static final class ArtifactInfo {

        private Artifact artifact;

        private File binDirectory;

        private File sourceDirectory;

        /** Exported packages used by all regions. */
        private Set<String> usedExportedPackages;

        /** Exported packages per region. */
        private final Map<String, Set<Clause>> usedExportedPackagesRegion = new HashMap<>();

        /** Flag if used as dependency */
        private final Map<String, String> useAsDependencyPerRegion = new HashMap<>();

        private final Set<File> includedResources = new HashSet<>();

        private final Set<String> nodeTypes = new HashSet<>();

        private List<License> licenses;

        private final Set<String> sources = new HashSet<>();

        public ArtifactInfo(final Artifact artifact) {
            this.artifact = artifact;
        }

        public ArtifactId getId() {
            return this.artifact.getId();
        }

        public Artifact getArtifact() {
            return this.artifact;
        }

        public File getBinDirectory() {
            return binDirectory;
        }

        public void setBinDirectory(File binDirectory) {
            this.binDirectory = binDirectory;
        }

        public File getSourceDirectory() {
            return sourceDirectory;
        }

        public void setSourceDirectory(File sourceDirectory) {
            this.sourceDirectory = sourceDirectory;
        }

        public Set<String> getUsedExportedPackages() {
            return usedExportedPackages;
        }

        public void setUsedExportedPackages(Set<String> usedExportedPackages) {
            this.usedExportedPackages = usedExportedPackages;
        }

        public String[] getUsedExportedPackageIncludes() {
            final Set<String> includes = new HashSet<>();
            for(final String pck : usedExportedPackages) {
                includes.add(pck.replace('.', '/').concat("/*"));
            }
            return includes.toArray(new String[includes.size()]);
        }

        public Set<Clause> getUsedExportedPackages(final String regionName) {
            return this.usedExportedPackagesRegion.get(regionName);
        }

        public void setUsedExportedPackages(final String regionName, final Set<Clause> usedExportedPackages, final String useAsDependency) {
            this.usedExportedPackagesRegion.put(regionName, usedExportedPackages);
            if ( useAsDependency != null ) {
                this.useAsDependencyPerRegion.put(regionName, useAsDependency);
            }
        }

        public String[] getUsedExportedPackageIncludes(final String regionName) {
            final Set<Clause> clauses = this.getUsedExportedPackages(regionName);
            final Set<String> includes = new HashSet<>();
            for(final Clause clause : clauses) {
                includes.add(clause.getName().replace('.', '/').concat("/*"));
            }
            return includes.toArray(new String[includes.size()]);
        }

        public boolean isUseAsDependencyPerRegion(final String regionName) {
            return this.useAsDependencyPerRegion.get(regionName) == null;
        }

        public String getNotUseAsDependencyPerRegionReason(final String regionName) {
            return this.useAsDependencyPerRegion.get(regionName);
        }

        public Set<File> getIncludedResources() {
            return includedResources;
        }

        /**
         * Get all node types from this artifact
         * @return The set of node types, might be empty
         */
        public Set<String> getNodeTypes() {
            return this.nodeTypes;
        }

        public List<License> getLicenses() {
            return licenses;
        }

        public void setLicenses(List<License> licenses) {
            this.licenses = licenses;
        }

        /**
         * Get the dependency artifacts
         * <ol>
         * <li>If {@code ApisUtil#API_IDS} is provided as metadata for the artifact,
         * the value is used as a list of artifacts
         * <li>If {@code ApisUtil#SCM_IDS} is provided as metadata for the artifact,
         * the value is used as a list of artifacts. The artifacts must have a classifier
         * set. The classifier is removed and then the artifacts are used
         * <li>The artifact itself is used
         * </ol>
         * @return The list of dependency artifacts
         * @throws MojoExecutionException If an incorrect configuration is found
         */
        public List<ArtifactId> getDependencyArtifacts() throws MojoExecutionException {
            final List<ArtifactId> dependencies = new ArrayList<>();
            final List<ArtifactId> apiIds = ApisUtil.getApiIds(artifact);
            if ( apiIds != null ) {
                for(final ArtifactId id : apiIds) {
                    dependencies.add(id);
                }
            } else {
                final List<ArtifactId> sourceIds = ApisUtil.getSourceIds(artifact);
                if ( sourceIds != null ) {
                    for(final ArtifactId id : sourceIds) {
                        dependencies.add(id.changeClassifier(null));
                    }
                } else {
                    dependencies.add(getId());
                }
            }
            return dependencies;
        }

        public void addSourceInfo(final ArtifactId id) {
            if ( id != null ) {
                this.sources.add(id.toMvnId());
            }
        }

        public void addSourceInfo(final String connection) {
            if ( connection != null ) {
                this.sources.add(connection);
            }
        }

        public Set<String> getSources() {
            return this.sources;
        }

        /* (non-Javadoc)
         * @see java.lang.Object#hashCode()
         */

        @Override
        public int hashCode() {
            return Objects.hash(artifact);
        }

        /* (non-Javadoc)
         * @see java.lang.Object#equals(java.lang.Object)
         */

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (!(obj instanceof ArtifactInfo))
                return false;
            ArtifactInfo other = (ArtifactInfo) obj;
            return Objects.equals(artifact, other.artifact);
        }
    }

    private final ApisConfiguration config;

    private final Map<ArtifactId, String> javadocClasspath = new HashMap<>();

    private final Set<String> packagesWithoutJavaClasses = new HashSet<>();

    private final Set<String> packagesWithoutSources = new HashSet<>();

    private final File deflatedBinDir;

    private final File deflatedSourcesDir;

    private final File checkedOutSourcesDir;

    private File javadocDir;

    private final List<ArtifactInfo> infos = new ArrayList<>();

    private final Feature feature;

    private final Map<ArtifactId, Model> modelCache = new HashMap<>();

    public ApisJarContext(final File mainDir, final Feature feature) throws MojoExecutionException {
        this.config = new ApisConfiguration(feature);
        this.feature = feature;

        // deflated and source dirs can be shared
        this.deflatedBinDir = new File(mainDir, "deflated-bin");
        this.deflatedSourcesDir = new File(mainDir, "deflated-sources");
        this.checkedOutSourcesDir = new File(mainDir, "checkouts");
    }

    public ApisConfiguration getConfig() {
        return this.config;
    }

    public ArtifactId getFeatureId() {
        return feature.getId();
    }

    public Feature getFeature() {
        return this.feature;
    }

    public File getDeflatedBinDir() {
        return deflatedBinDir;
    }

    public File getDeflatedSourcesDir() {
        return deflatedSourcesDir;
    }

    public File getCheckedOutSourcesDir() {
        return checkedOutSourcesDir;
    }

    public void addJavadocClasspath(final ArtifactId artifactId, final String classpath) {
        javadocClasspath.put(artifactId, classpath);
    }

    public Map<ArtifactId, String> getJavadocClasspath() {
        return javadocClasspath;
    }

    public File getJavadocDir() {
        return javadocDir;
    }

    public void setJavadocDir(final File javadocDir) {
        this.javadocDir = javadocDir;
    }

    public Set<String> getPackagesWithoutJavaClasses() {
        return packagesWithoutJavaClasses;
    }

    public Set<String> getPackagesWithoutSources() {
        return packagesWithoutSources;
    }

    public ArtifactInfo addArtifactInfo(final Artifact artifact) {
        final ArtifactInfo info = new ArtifactInfo(artifact);
        this.infos.add(info);

        return info;
    }

    public ArtifactInfo getArtifactInfo(final ArtifactId artifactId) {
        for(final ArtifactInfo i : this.infos) {
            if ( i.getArtifact().getId().equals(artifactId)) {
                return i;
            }
        }
        return null;
    }

    public List<ArtifactInfo> getArtifactInfos() {
        return this.infos;
    }

    public Map<ArtifactId, Model> getModelCache() {
        return this.modelCache;
    }

    public Collection<ArtifactInfo> getArtifactInfos(final String regionName, final boolean omitDependencyArtifacts) {
        final Map<ArtifactId, ArtifactInfo> result = new TreeMap<>();
        for(final ArtifactInfo info : this.infos) {
            final Set<Clause> pcks = info.getUsedExportedPackages(regionName);
            if ( pcks != null && !pcks.isEmpty() ) {
                if ( !omitDependencyArtifacts || !info.isUseAsDependencyPerRegion(regionName) ) {
                    result.put(info.getId(), info);
                }
            }
        }
        return result.values();
    }

    /**
     * Find a an artifact
     * If dependency repositories are configured, one of them must provide the artifact
     * @param log Logger
     * @param id The artifact id
     * @return {@code true} if the artifact could be found.
     * @throws MojoExecutionException
     */
    private boolean findDependencyArtifact(final Log log, final ArtifactId id) throws MojoExecutionException {
        boolean result = true;
        if ( !this.getConfig().getDependencyRepositories().isEmpty() ) {
            result = false;
            log.debug("Trying to resolve ".concat(id.toMvnId()).concat(" from ").concat(this.getConfig().getDependencyRepositories().toString()));
            for(final String server : this.getConfig().getDependencyRepositories()) {
                try {
                    final URL url = new URL(server.concat(id.toMvnPath()));
                    try {
                        url.openConnection().getInputStream().close();
                        log.debug("Found ".concat(id.toMvnId()).concat(" at ").concat(url.toString()));
                        result = true;
                        break;
                    } catch (IOException e) {
                        // not available
                        log.debug("Missed ".concat(id.toMvnId()).concat(" at ").concat(url.toString()).concat(" : ").concat(e.toString()));
                    }
                } catch ( final MalformedURLException mue) {
                    throw new MojoExecutionException("Unable to find dependency on ".concat(server), mue);
                }
            }
        }
        return result;
    }

    /**
     * Check if all dependency artifacts can be found
     * @param log The logger
     * @param info The artifact info
     * @return {@code true} if all artifacts are publically available
     * @throws MojoExecutionException If an incorrect configuration is found
     */
    public boolean findDependencyArtifact(final Log log, final ArtifactInfo info) throws MojoExecutionException {
        boolean result = true;
        for(final ArtifactId id : info.getDependencyArtifacts()) {
            if ( !findDependencyArtifact(log, id) ) {
                result = false;
                break;
            }
        }
        return result;
    }
}
