/*
 * 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.plugins.pmd;

import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import net.sourceforge.pmd.RulePriority;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.pmd.model.ProcessingError;
import org.apache.maven.plugins.pmd.model.SuppressedViolation;
import org.apache.maven.plugins.pmd.model.Violation;
import org.apache.maven.reporting.AbstractMavenReportRenderer;
import org.codehaus.plexus.i18n.I18N;
import org.codehaus.plexus.util.StringUtils;

/**
 * Render the PMD violations into Doxia events.
 *
 * @author Brett Porter
 * @version $Id$
 */
public class PmdReportRenderer extends AbstractMavenReportRenderer {
    private final Log log;

    private final I18N i18n;

    private final Locale locale;

    private final Map<File, PmdFileInfo> files;

    // TODO Should not share state
    private String currentFilename;

    private final Collection<Violation> violations;

    private boolean renderRuleViolationPriority;

    private final boolean renderViolationsByPriority;

    private final boolean aggregate;

    private Collection<SuppressedViolation> suppressedViolations = new ArrayList<>();

    private Collection<ProcessingError> processingErrors = new ArrayList<>();

    public PmdReportRenderer(
            Log log,
            Sink sink,
            I18N i18n,
            Locale locale,
            Map<File, PmdFileInfo> files,
            Collection<Violation> violations,
            boolean renderRuleViolationPriority,
            boolean renderViolationsByPriority,
            boolean aggregate) {
        super(sink);
        this.log = log;
        this.i18n = i18n;
        this.locale = locale;
        this.files = files;
        this.violations = violations;
        this.renderRuleViolationPriority = renderRuleViolationPriority;
        this.renderViolationsByPriority = renderViolationsByPriority;
        this.aggregate = aggregate;
    }

    public void setSuppressedViolations(Collection<SuppressedViolation> suppressedViolations) {
        this.suppressedViolations = suppressedViolations;
    }

    public void setProcessingErrors(Collection<ProcessingError> processingErrors) {
        this.processingErrors = processingErrors;
    }

    @Override
    public String getTitle() {
        return getI18nString("title");
    }

    /**
     * @param key The key.
     * @return The translated string.
     */
    private String getI18nString(String key) {
        return i18n.getString("pmd-report", locale, "report.pmd." + key);
    }

    protected void renderBody() {
        startSection(getTitle());

        sink.paragraph();
        sink.text(getI18nString("pmdlink") + " ");
        link("https://pmd.github.io", "PMD");
        sink.text(" " + AbstractPmdReport.getPmdVersion() + ".");
        sink.paragraph_();

        if (!violations.isEmpty()) {
            renderViolationsByPriority();

            renderViolations();
        } else {
            paragraph(getI18nString("noProblems"));
        }

        renderSuppressedViolations();

        renderProcessingErrors();

        endSection();
    }

    private void startFileSection(String currentFilename, PmdFileInfo fileInfo) {
        // prepare the filename
        this.currentFilename = shortenFilename(currentFilename, fileInfo);

        startSection(makeFileSectionName(this.currentFilename, fileInfo));

        startTable();
        sink.tableRow();
        tableHeaderCell(getI18nString("column.rule"));
        tableHeaderCell(getI18nString("column.violation"));
        if (this.renderRuleViolationPriority) {
            tableHeaderCell(getI18nString("column.priority"));
        }
        tableHeaderCell(getI18nString("column.line"));
        sink.tableRow_();
    }

    private void endFileSection() {
        endTable();
        endSection();
    }

    private void addRuleName(Violation ruleViolation) {
        boolean hasUrl = StringUtils.isNotBlank(ruleViolation.getExternalInfoUrl());

        if (hasUrl) {
            sink.link(ruleViolation.getExternalInfoUrl());
        }

        sink.text(ruleViolation.getRule());

        if (hasUrl) {
            sink.link_();
        }
    }

    private void renderSingleRuleViolation(Violation ruleViolation, PmdFileInfo fileInfo) {
        sink.tableRow();
        sink.tableCell();
        addRuleName(ruleViolation);
        sink.tableCell_();
        // May contain content not legit for #tableCell()
        sink.tableCell();
        sink.text(ruleViolation.getText());
        sink.tableCell_();

        if (this.renderRuleViolationPriority) {
            tableCell(String.valueOf(
                    RulePriority.valueOf(ruleViolation.getPriority()).getPriority()));
        }

        sink.tableCell();

        int beginLine = ruleViolation.getBeginline();
        outputLineLink(beginLine, fileInfo);
        int endLine = ruleViolation.getEndline();
        if (endLine != beginLine) {
            sink.text("&#x2013;"); // \u2013 is a medium long dash character
            outputLineLink(endLine, fileInfo);
        }

        sink.tableCell_();
        sink.tableRow_();
    }

    // PMD might run the analysis multi-threaded, so the violations might be reported
    // out of order. We sort them here by filename and line number before writing them to
    // the report.
    private void renderViolations() {
        startSection(getI18nString("files"));

        // TODO files summary
        renderViolationsTable(violations);

        endSection();
    }

    private void renderViolationsByPriority() {
        if (!renderViolationsByPriority) {
            return;
        }

        boolean oldPriorityColumn = this.renderRuleViolationPriority;
        this.renderRuleViolationPriority = false;

        startSection(getI18nString("violationsByPriority"));

        Map<RulePriority, List<Violation>> violationsByPriority = new HashMap<>();
        for (Violation violation : violations) {
            RulePriority priority = RulePriority.valueOf(violation.getPriority());
            List<Violation> violationSegment = violationsByPriority.get(priority);
            if (violationSegment == null) {
                violationSegment = new ArrayList<>();
                violationsByPriority.put(priority, violationSegment);
            }
            violationSegment.add(violation);
        }

        for (RulePriority priority : RulePriority.values()) {
            List<Violation> violationsWithPriority = violationsByPriority.get(priority);
            if (violationsWithPriority == null || violationsWithPriority.isEmpty()) {
                continue;
            }

            startSection(getI18nString("priority") + " " + priority.getPriority());

            renderViolationsTable(violationsWithPriority);

            endSection();
        }

        if (violations.isEmpty()) {
            paragraph(getI18nString("noProblems"));
        }

        endSection();

        this.renderRuleViolationPriority = oldPriorityColumn;
    }

    private void renderViolationsTable(Collection<Violation> violationSegment) {
        List<Violation> violationSegmentCopy = new ArrayList<>(violationSegment);
        Collections.sort(violationSegmentCopy, new Comparator<Violation>() {
            /** {@inheritDoc} */
            public int compare(Violation o1, Violation o2) {
                int filenames = o1.getFileName().compareTo(o2.getFileName());
                if (filenames == 0) {
                    return o1.getBeginline() - o2.getBeginline();
                } else {
                    return filenames;
                }
            }
        });

        boolean fileSectionStarted = false;
        String previousFilename = null;
        for (Violation ruleViolation : violationSegmentCopy) {
            String currentFn = ruleViolation.getFileName();
            PmdFileInfo fileInfo = determineFileInfo(currentFn);

            if (!currentFn.equalsIgnoreCase(previousFilename) && fileSectionStarted) {
                endFileSection();
                fileSectionStarted = false;
            }
            if (!fileSectionStarted) {
                startFileSection(currentFn, fileInfo);
                fileSectionStarted = true;
            }

            renderSingleRuleViolation(ruleViolation, fileInfo);

            previousFilename = currentFn;
        }

        if (fileSectionStarted) {
            endFileSection();
        }
    }

    private void outputLineLink(int line, PmdFileInfo fileInfo) {
        String xrefLocation = null;
        if (fileInfo != null) {
            xrefLocation = fileInfo.getXrefLocation();
        }

        if (xrefLocation != null) {
            sink.link(xrefLocation + "/" + currentFilename.replaceAll("\\.java$", ".html") + "#L" + line);
        }
        sink.text(String.valueOf(line));
        if (xrefLocation != null) {
            sink.link_();
        }
    }

    // PMD might run the analysis multi-threaded, so the suppressed violations might be reported
    // out of order. We sort them here by filename before writing them to
    // the report.
    private void renderSuppressedViolations() {
        if (suppressedViolations.isEmpty()) {
            return;
        }

        startSection(getI18nString("suppressedViolations.title"));

        List<SuppressedViolation> suppressedViolationsCopy = new ArrayList<>(suppressedViolations);
        Collections.sort(suppressedViolationsCopy, new Comparator<SuppressedViolation>() {
            @Override
            public int compare(SuppressedViolation o1, SuppressedViolation o2) {
                return o1.getFilename().compareTo(o2.getFilename());
            }
        });

        startTable();
        tableHeader(new String[] {
            getI18nString("suppressedViolations.column.filename"),
            getI18nString("suppressedViolations.column.ruleMessage"),
            getI18nString("suppressedViolations.column.suppressionType"),
            getI18nString("suppressedViolations.column.userMessage")
        });

        for (SuppressedViolation suppressedViolation : suppressedViolationsCopy) {
            String filename = suppressedViolation.getFilename();
            PmdFileInfo fileInfo = determineFileInfo(filename);
            filename = shortenFilename(filename, fileInfo);

            // May contain content not legit for #tableCell()
            sink.tableRow();
            tableCell(filename);
            sink.tableCell();
            sink.text(suppressedViolation.getRuleMessage());
            sink.tableCell_();
            tableCell(suppressedViolation.getSuppressionType());
            sink.tableCell();
            sink.text(suppressedViolation.getUserMessage());
            sink.tableCell_();
            sink.tableRow_();
        }

        endTable();
        endSection();
    }

    private void renderProcessingErrors() {
        if (processingErrors.isEmpty()) {
            return;
        }

        // sort the problem by filename first, since PMD is executed multi-threaded
        // and might reports the results unsorted
        List<ProcessingError> processingErrorsCopy = new ArrayList<>(processingErrors);
        Collections.sort(processingErrorsCopy, new Comparator<ProcessingError>() {
            @Override
            public int compare(ProcessingError e1, ProcessingError e2) {
                return e1.getFilename().compareTo(e2.getFilename());
            }
        });

        startSection(getI18nString("processingErrors.title"));

        startTable();
        tableHeader(new String[] {
            getI18nString("processingErrors.column.filename"), getI18nString("processingErrors.column.problem")
        });

        for (ProcessingError error : processingErrorsCopy) {
            renderSingleProcessingError(error);
        }

        endTable();
        endSection();
    }

    private void renderSingleProcessingError(ProcessingError error) {
        String filename = error.getFilename();
        PmdFileInfo fileInfo = determineFileInfo(filename);
        filename = makeFileSectionName(shortenFilename(filename, fileInfo), fileInfo);

        sink.tableRow();
        tableCell(filename);
        sink.tableCell();
        sink.text(error.getMsg());
        sink.verbatim(null);
        sink.rawText(error.getDetail());
        sink.verbatim_();
        sink.tableCell_();
        sink.tableRow_();
    }

    private String shortenFilename(String filename, PmdFileInfo fileInfo) {
        String result = filename;
        if (fileInfo != null && fileInfo.getSourceDirectory() != null) {
            result = StringUtils.substring(
                    result, fileInfo.getSourceDirectory().getAbsolutePath().length() + 1);
        }
        return StringUtils.replace(result, "\\", "/");
    }

    private String makeFileSectionName(String filename, PmdFileInfo fileInfo) {
        if (aggregate && fileInfo != null && fileInfo.getProject() != null) {
            return fileInfo.getProject().getName() + " - " + filename;
        }
        return filename;
    }

    private PmdFileInfo determineFileInfo(String filename) {
        try {
            File canonicalFilename = new File(filename).getCanonicalFile();
            PmdFileInfo fileInfo = files.get(canonicalFilename);
            if (fileInfo == null) {
                log.warn("Couldn't determine PmdFileInfo for file " + filename + " (canonical: " + canonicalFilename
                        + "). XRef links won't be available.");
            }
            return fileInfo;
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }
}
