/*
 * 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.maven.plugin.plugin.report;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.AbstractMap.SimpleEntry;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet.Semantics;
import org.apache.maven.doxia.util.HtmlTools;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.Parameter;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.apache.maven.tools.plugin.EnhancedParameterWrapper;
import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
import org.apache.maven.tools.plugin.javadoc.JavadocLinkGenerator;
import org.apache.maven.tools.plugin.util.PluginUtils;
import org.codehaus.plexus.i18n.I18N;

public class GoalRenderer extends AbstractPluginReportRenderer {

    /** Regular expression matching an XHTML link with group 1 = link target, group 2 = link label. */
    private static final Pattern HTML_LINK_PATTERN = Pattern.compile("<a href=\\\"([^\\\"]*)\\\">(.*?)</a>");

    /** The directory where the generated site is written. Used for resolving relative links to javadoc. */
    private final File reportOutputDirectory;

    private final MojoDescriptor descriptor;
    private final boolean disableInternalJavadocLinkValidation;

    private final Log log;

    public GoalRenderer(
            Sink sink,
            I18N i18n,
            Locale locale,
            MavenProject project,
            MojoDescriptor descriptor,
            File reportOutputDirectory,
            boolean disableInternalJavadocLinkValidation,
            Log log) {
        super(sink, locale, i18n, project);
        this.reportOutputDirectory = reportOutputDirectory;
        this.descriptor = descriptor;
        this.disableInternalJavadocLinkValidation = disableInternalJavadocLinkValidation;
        this.log = log;
    }

    @Override
    public String getTitle() {
        return descriptor.getFullGoalName();
    }

    @Override
    protected void renderBody() {
        startSection(descriptor.getFullGoalName());
        renderReportNotice();
        renderDescription("fullname", descriptor.getPluginDescriptor().getId() + ":" + descriptor.getGoal(), false);

        String context = "goal " + descriptor.getGoal();
        if (StringUtils.isNotEmpty(descriptor.getDeprecated())) {
            renderDescription("deprecated", getXhtmlWithValidatedLinks(descriptor.getDeprecated(), context), true);
        }
        if (StringUtils.isNotEmpty(descriptor.getDescription())) {
            renderDescription("description", getXhtmlWithValidatedLinks(descriptor.getDescription(), context), true);
        } else {
            renderDescription("description", getI18nString("nodescription"), false);
        }
        renderAttributes();

        List<Parameter> parameterList = filterParameters(
                descriptor.getParameters() != null ? descriptor.getParameters() : Collections.emptyList());
        if (parameterList.isEmpty()) {
            startSection(getI18nString("parameters"));
            sink.paragraph();
            sink.text(getI18nString("noParameter"));
            sink.paragraph_();
            endSection();
        } else {
            renderParameterOverviewTable(
                    getI18nString("requiredParameters"),
                    parameterList.stream().filter(Parameter::isRequired).iterator());
            renderParameterOverviewTable(
                    getI18nString("optionalParameters"),
                    parameterList.stream().filter(p -> !p.isRequired()).iterator());
            renderParameterDetails(parameterList.iterator());
        }
        endSection();
    }

    /** Filter parameters to only retain those which must be documented, i.e. neither components nor read-only ones.
     *
     * @param parameterList not null
     * @return the parameters list without components. */
    private static List<Parameter> filterParameters(Collection<Parameter> parameterList) {
        return parameterList.stream()
                .filter(p -> p.isEditable()
                        && (p.getExpression() == null || !p.getExpression().startsWith("${component.")))
                .collect(Collectors.toList());
    }

    private void renderReportNotice() {
        if (PluginUtils.isMavenReport(descriptor.getImplementation(), project)) {
            renderDescription("notice.prefix", getI18nString("notice.isMavenReport"), false);
        }
    }

    /**
     * A description consists of a term/prefix and the actual description text
     */
    private void renderDescription(String prefixKey, String description, boolean isHtmlMarkup) {
        // TODO: convert to dt and dd elements
        renderDescriptionPrefix(prefixKey);
        sink.paragraph();
        if (isHtmlMarkup) {
            sink.rawText(description);
        } else {
            sink.text(description);
        }
        sink.paragraph_(); // p
    }

    private void renderDescriptionPrefix(String prefixKey) {
        sink.paragraph();
        sink.inline(Semantics.STRONG);
        sink.text(getI18nString(prefixKey));
        sink.inline_();
        sink.text(":");
        sink.paragraph_();
    }

    @SuppressWarnings("deprecation")
    private void renderAttributes() {
        renderDescriptionPrefix("attributes");
        sink.list();

        renderAttribute(descriptor.isProjectRequired(), "projectRequired");
        renderAttribute(descriptor.isRequiresReports(), "reportingMojo");
        renderAttribute(descriptor.isAggregator(), "aggregator");
        renderAttribute(descriptor.isDirectInvocationOnly(), "directInvocationOnly");
        renderAttribute(descriptor.isDependencyResolutionRequired(), "dependencyResolutionRequired");

        if (descriptor instanceof ExtendedMojoDescriptor) {
            ExtendedMojoDescriptor extendedDescriptor = (ExtendedMojoDescriptor) descriptor;
            renderAttribute(extendedDescriptor.getDependencyCollectionRequired(), "dependencyCollectionRequired");
        }

        renderAttribute(descriptor.isThreadSafe(), "threadSafe");
        renderAttribute(!descriptor.isThreadSafe(), "notThreadSafe");
        renderAttribute(descriptor.getSince(), "since");
        renderAttribute(descriptor.getPhase(), "phase");
        renderAttribute(descriptor.getExecutePhase(), "executePhase");
        renderAttribute(descriptor.getExecuteGoal(), "executeGoal");
        renderAttribute(descriptor.getExecuteLifecycle(), "executeLifecycle");
        renderAttribute(descriptor.isOnlineRequired(), "onlineRequired");
        renderAttribute(!descriptor.isInheritedByDefault(), "notInheritedByDefault");

        sink.list_();
    }

    private void renderAttribute(boolean condition, String attributeKey) {
        renderAttribute(condition, attributeKey, Optional.empty());
    }

    private void renderAttribute(String conditionAndCodeArgument, String attributeKey) {
        renderAttribute(
                StringUtils.isNotEmpty(conditionAndCodeArgument),
                attributeKey,
                Optional.ofNullable(conditionAndCodeArgument));
    }

    private void renderAttribute(boolean condition, String attributeKey, Optional<String> codeArgument) {
        if (condition) {
            sink.listItem();
            linkPatternedText(getI18nString(attributeKey));
            if (codeArgument.isPresent()) {
                text(": ");
                sink.inline(Semantics.CODE);
                sink.text(codeArgument.get());
                sink.inline_();
            }
            text(".");
            sink.listItem_();
        }
    }

    private void renderParameterOverviewTable(String title, Iterator<Parameter> parameters) {
        // don't emit empty tables
        if (!parameters.hasNext()) {
            return;
        }
        startSection(title);
        startTable();
        tableHeader(new String[] {
            getI18nString("parameter.name.header"),
            getI18nString("parameter.type.header"),
            getI18nString("parameter.since.header"),
            getI18nString("parameter.description.header")
        });
        while (parameters.hasNext()) {
            renderParameterOverviewTableRow(parameters.next());
        }
        endTable();
        endSection();
    }

    private void renderTableCellWithCode(String text) {
        renderTableCellWithCode(text, Optional.empty());
    }

    private void renderTableCellWithCode(String text, Optional<String> link) {
        sink.tableCell();
        if (link.isPresent()) {
            sink.link(link.get(), null);
        }
        sink.inline(Semantics.CODE);
        sink.text(text);
        sink.inline_();
        if (link.isPresent()) {
            sink.link_();
        }
        sink.tableCell_();
    }

    private void renderParameterOverviewTableRow(Parameter parameter) {
        sink.tableRow();
        // name
        // link to appropriate section
        renderTableCellWithCode(
                format("parameter.name", parameter.getName()),
                // no need for additional URI encoding as it returns only URI safe characters
                Optional.of("#" + HtmlTools.encodeId(parameter.getName())));

        // type
        Map.Entry<String, Optional<String>> type = getLinkedType(parameter, true);
        renderTableCellWithCode(type.getKey(), type.getValue());

        // since
        String since = StringUtils.defaultIfEmpty(parameter.getSince(), "-");
        renderTableCellWithCode(since);

        // description
        sink.tableCell();
        String description;
        String context = "Parameter " + parameter.getName() + " in goal " + descriptor.getGoal();
        renderDeprecatedParameterDescription(parameter.getDeprecated(), context);
        if (StringUtils.isNotEmpty(parameter.getDescription())) {
            description = getXhtmlWithValidatedLinks(parameter.getDescription(), context);
        } else {
            description = getI18nString("nodescription");
        }
        sink.rawText(description);
        renderTableCellDetail("parameter.defaultValue", parameter.getDefaultValue());
        renderTableCellDetail("parameter.property", getPropertyFromExpression(parameter.getExpression()));
        renderTableCellDetail("parameter.alias", parameter.getAlias());
        sink.tableCell_();

        sink.tableRow_();
    }

    private void renderParameterDetails(Iterator<Parameter> parameters) {

        startSection(getI18nString("parameter.details"));

        while (parameters.hasNext()) {
            Parameter parameter = parameters.next();
            // deprecated anchor for backwards-compatibility with XDoc (upper and lower case)
            // TODO: replace once migrated to Doxia 2.x with two-arg startSection(String, String) method
            sink.anchor(parameter.getName());
            sink.anchor_();

            startSection(format("parameter.name", parameter.getName()));
            String context = "Parameter " + parameter.getName() + " in goal " + descriptor.getGoal();
            renderDeprecatedParameterDescription(parameter.getDeprecated(), context);
            sink.division();
            if (StringUtils.isNotEmpty(parameter.getDescription())) {
                sink.rawText(getXhtmlWithValidatedLinks(parameter.getDescription(), context));
            } else {
                sink.text(getI18nString("nodescription"));
            }
            sink.division_();

            sink.list();
            Map.Entry<String, Optional<String>> typeAndLink = getLinkedType(parameter, false);
            renderDetail(getI18nString("parameter.type"), typeAndLink.getKey(), typeAndLink.getValue());

            if (StringUtils.isNotEmpty(parameter.getSince())) {
                renderDetail(getI18nString("parameter.since"), parameter.getSince());
            }

            if (parameter.isRequired()) {
                renderDetail(getI18nString("parameter.required"), getI18nString("yes"));
            } else {
                renderDetail(getI18nString("parameter.required"), getI18nString("no"));
            }

            String expression = parameter.getExpression();
            String property = getPropertyFromExpression(expression);
            if (property == null) {
                renderDetail(getI18nString("parameter.expression"), expression);
            } else {
                renderDetail(getI18nString("parameter.property"), property);
            }

            renderDetail(getI18nString("parameter.defaultValue"), parameter.getDefaultValue());

            renderDetail(getI18nString("parameter.alias"), parameter.getAlias());

            sink.list_(); // ul

            if (parameters.hasNext()) {
                sink.horizontalRule();
            }
            endSection();
        }
        endSection();
    }

    private void renderDeprecatedParameterDescription(String deprecated, String context) {
        if (StringUtils.isNotEmpty(deprecated)) {
            String deprecatedXhtml = getXhtmlWithValidatedLinks(deprecated, context);
            sink.division();
            sink.inline(Semantics.STRONG);
            sink.text(getI18nString("parameter.deprecated"));
            sink.inline_();
            sink.lineBreak();
            sink.rawText(deprecatedXhtml);
            sink.division_();
            sink.lineBreak();
        }
    }

    private void renderTableCellDetail(String nameKey, String value) {
        if (StringUtils.isNotEmpty(value)) {
            sink.lineBreak();
            sink.inline(Semantics.STRONG);
            sink.text(getI18nString(nameKey));
            sink.inline_();
            sink.text(": ");
            sink.inline(Semantics.CODE);
            sink.text(value);
            sink.inline_();
        }
    }

    private void renderDetail(String param, String value) {
        renderDetail(param, value, Optional.empty());
    }

    private void renderDetail(String param, String value, Optional<String> valueLink) {
        if (value != null && !value.isEmpty()) {
            sink.listItem();
            sink.inline(Semantics.STRONG);
            sink.text(param);
            sink.inline_();
            sink.text(": ");
            if (valueLink.isPresent()) {
                sink.link(valueLink.get());
            }
            sink.inline(Semantics.CODE);
            sink.text(value);
            sink.inline_();
            if (valueLink.isPresent()) {
                sink.link_();
            }
            sink.listItem_();
        }
    }

    private static String getPropertyFromExpression(String expression) {
        if ((expression != null && !expression.isEmpty())
                && expression.startsWith("${")
                && expression.endsWith("}")
                && !expression.substring(2).contains("${")) {
            // expression="${xxx}" -> property="xxx"
            return expression.substring(2, expression.length() - 1);
        }
        // no property can be extracted
        return null;
    }

    static String getShortType(String type) {
        // split into type arguments and main type
        int startTypeArguments = type.indexOf('<');
        if (startTypeArguments == -1) {
            return getShortTypeOfSimpleType(type);
        } else {
            StringBuilder shortType = new StringBuilder();
            shortType.append(getShortTypeOfSimpleType(type.substring(0, startTypeArguments)));
            shortType
                    .append("<")
                    .append(getShortTypeOfTypeArgument(type.substring(startTypeArguments + 1, type.lastIndexOf(">"))))
                    .append(">");
            return shortType.toString();
        }
    }

    private static String getShortTypeOfTypeArgument(String type) {
        String[] typeArguments = type.split(",\\s*");
        StringBuilder shortType = new StringBuilder();
        for (int i = 0; i < typeArguments.length; i++) {
            String typeArgument = typeArguments[i];
            if (typeArgument.contains("<")) {
                // nested type arguments lead to ellipsis
                return "...";
            } else {
                shortType.append(getShortTypeOfSimpleType(typeArgument));
                if (i < typeArguments.length - 1) {
                    shortType.append(",");
                }
            }
        }
        return shortType.toString();
    }

    private static String getShortTypeOfSimpleType(String type) {
        int index = type.lastIndexOf('.');
        return type.substring(index + 1);
    }

    private Map.Entry<String, Optional<String>> getLinkedType(Parameter parameter, boolean isShortType) {
        final String typeValue;
        if (isShortType) {
            typeValue = getShortType(parameter.getType());
        } else {
            typeValue = parameter.getType();
        }
        URI uri = null;
        if (parameter instanceof EnhancedParameterWrapper) {
            EnhancedParameterWrapper enhancedParameter = (EnhancedParameterWrapper) parameter;
            if (enhancedParameter.getTypeJavadocUrl() != null) {
                URI javadocUrl = enhancedParameter.getTypeJavadocUrl();
                // optionally check if link is valid
                if (javadocUrl.isAbsolute()
                        || disableInternalJavadocLinkValidation
                        || JavadocLinkGenerator.isLinkValid(javadocUrl, reportOutputDirectory.toPath())) {
                    uri = enhancedParameter.getTypeJavadocUrl();
                }
            }
        }
        // rely on the encoded URI
        return new SimpleEntry<>(typeValue, Optional.ofNullable(uri).map(URI::toASCIIString));
    }

    String getXhtmlWithValidatedLinks(String xhtmlText, String context) {
        if (disableInternalJavadocLinkValidation) {
            return xhtmlText;
        }
        StringBuffer sanitizedXhtmlText = new StringBuffer();
        // find all links which are not absolute
        Matcher matcher = HTML_LINK_PATTERN.matcher(xhtmlText);
        while (matcher.find()) {
            URI link;
            try {
                link = new URI(matcher.group(1));
                if (!link.isAbsolute() && !JavadocLinkGenerator.isLinkValid(link, reportOutputDirectory.toPath())) {
                    matcher.appendReplacement(sanitizedXhtmlText, matcher.group(2));
                    log.debug(String.format("Removed invalid link %s in %s", link, context));
                } else {
                    matcher.appendReplacement(sanitizedXhtmlText, matcher.group(0));
                }
            } catch (URISyntaxException e) {
                log.warn(String.format(
                        "Invalid URI %s found in %s. Cannot validate, leave untouched", matcher.group(1), context));
                matcher.appendReplacement(sanitizedXhtmlText, matcher.group(0));
            }
        }
        matcher.appendTail(sanitizedXhtmlText);
        return sanitizedXhtmlText.toString();
    }

    /** Convenience method.
     *
     * @param key  not null
     * @param arg1 not null
     * @return Localized, formatted text identified by <code>key</code>.
     * @see #format(String, Object[]) */
    private String format(String key, Object arg1) {
        return format(key, new Object[] {arg1});
    }

    /** Looks up the value for <code>key</code> in the <code>ResourceBundle</code>, then formats that value for the specified
     * <code>Locale</code> using <code>args</code>.
     *
     * @param key  not null
     * @param args not null
     * @return Localized, formatted text identified by <code>key</code>. */
    private String format(String key, Object[] args) {
        String pattern = getI18nString(key);
        // we don't need quoting so spare us the confusion in the resource bundle to double them up in some keys
        pattern = StringUtils.replace(pattern, "'", "''");

        MessageFormat messageFormat = new MessageFormat(pattern, locale);
        return messageFormat.format(args);
    }

    @Override
    protected String getI18nSection() {
        return "plugin.goal";
    }
}
