/*
 * 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.netbeans.modules.maven.coverage;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.text.Document;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.project.Project;
import org.netbeans.modules.gsf.codecoverage.api.CoverageManager;
import org.netbeans.modules.gsf.codecoverage.api.CoverageProvider;
import org.netbeans.modules.gsf.codecoverage.api.CoverageType;
import org.netbeans.modules.gsf.codecoverage.api.FileCoverageDetails;
import org.netbeans.modules.gsf.codecoverage.api.FileCoverageSummary;
import org.netbeans.modules.maven.api.NbMavenProject;
import org.netbeans.modules.maven.api.PluginPropertyUtils;
import org.netbeans.modules.maven.api.classpath.ProjectSourcesClassPathProvider;
import org.netbeans.spi.project.ProjectServiceProvider;
import org.openide.filesystems.FileChangeAdapter;
import org.openide.filesystems.FileChangeListener;
import org.openide.filesystems.FileEvent;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Pair;
import org.openide.xml.XMLUtil;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

@ProjectServiceProvider(service=CoverageProvider.class, projectType="org-netbeans-modules-maven") // not limited to a packaging
public final class MavenCoverageProvider implements CoverageProvider {

    private static final String GROUP_COBERTURA = "org.codehaus.mojo"; // NOI18N
    private static final String ARTIFACT_COBERTURA = "cobertura-maven-plugin"; // NOI18N
    private static final String GROUP_JOCOCO = "org.jacoco";
    private static final String ARTIFACT_JOCOCO = "jacoco-maven-plugin";

    private static final Logger LOG = Logger.getLogger(MavenCoverageProvider.class.getName());

    private final Project p;
    private Map<String, MavenSummary> summaryCache;

    public MavenCoverageProvider(Project p) {
        this.p = p;
    }

    public @Override boolean supportsHitCounts() {
        return true;
    }

    public @Override boolean supportsAggregation() {
        return false;
    }

    private boolean hasPlugin(String groupId, String artifactId) {
        NbMavenProject prj = p.getLookup().lookup(NbMavenProject.class);
        if (prj == null) {
            return false;
        }
        MavenProject mp = prj.getMavenProject();
        if (PluginPropertyUtils.getReportPluginVersion(mp, groupId, artifactId) != null) {
            return true;
        }
        if (PluginPropertyUtils.getPluginVersion(mp, groupId, artifactId) != null) {
            // For whatever reason, was configured as a direct build plugin... fine.
            return true;
        }
        // In fact you _could_ just run the plugin directly here... but perhaps the user did not want to do so.
        return false;
    }

    public @Override boolean isEnabled() {
        return hasPlugin(GROUP_COBERTURA, ARTIFACT_COBERTURA) || hasPlugin(GROUP_JOCOCO, ARTIFACT_JOCOCO);
    }

    public @Override boolean isAggregating() {
        throw new UnsupportedOperationException();
    }

    public @Override void setAggregating(boolean aggregating) {
        throw new UnsupportedOperationException();
    }

    public @Override Set<String> getMimeTypes() {
        return Collections.singleton("text/x-java"); // NOI18N
    }

    public @Override void setEnabled(boolean enabled) {
        // XXX add plugin configuration here if not already present
    }

    private @CheckForNull File report() {
        if (hasPlugin(GROUP_JOCOCO, ARTIFACT_JOCOCO)) {
            String outputDirectory = PluginPropertyUtils.getReportPluginProperty(p, GROUP_JOCOCO, ARTIFACT_JOCOCO, "outputDirectory", null);
            if (outputDirectory == null) {
                outputDirectory = PluginPropertyUtils.getPluginProperty(p, GROUP_JOCOCO, ARTIFACT_JOCOCO, "outputDirectory", "report", null);
            }
            if (outputDirectory == null) {
                try {
                    outputDirectory = (String) PluginPropertyUtils.createEvaluator(p).evaluate("${project.reporting.outputDirectory}/jacoco");
                } catch (ExpressionEvaluationException x) {
                    LOG.log(Level.WARNING, null, x);
                    return null;
                }
            }
            File outputFile = FileUtil.normalizeFile(new File(outputDirectory));
            return FileUtil.normalizeFile(new File(outputDirectory, "jacoco.xml"));
        } else {
        String outputDirectory = PluginPropertyUtils.getReportPluginProperty(p, GROUP_COBERTURA, ARTIFACT_COBERTURA, "outputDirectory", null);
        if (outputDirectory == null) {
            outputDirectory = PluginPropertyUtils.getPluginProperty(p, GROUP_COBERTURA, ARTIFACT_COBERTURA, "outputDirectory", null, null);
        }
        if (outputDirectory == null) {
            try {
                outputDirectory = (String) PluginPropertyUtils.createEvaluator(p).evaluate("${project.reporting.outputDirectory}/cobertura");
            } catch (ExpressionEvaluationException x) {
                LOG.log(Level.WARNING, null, x);
                return null;
            }
        }
        return FileUtil.normalizeFile(new File(outputDirectory, "coverage.xml"));
        }
    }

    public @Override synchronized void clear() {
        File r = report();
        if (r != null && r.isFile() && r.delete()) {
            summaryCache = null;
            CoverageManager.INSTANCE.resultsUpdated(p, MavenCoverageProvider.this);
        }
    }

    private FileChangeListener listener;

    private @CheckForNull Pair<File, org.w3c.dom.Document> parse() {
        File r = report();
        if (r == null) {
            LOG.fine("undefined report location");
            return null;
        }
        CoverageManager.INSTANCE.setEnabled(p, true); // XXX otherwise it defaults to disabled?? not clear where to call this
        if (listener == null) {
            listener = new FileChangeAdapter() {
                public @Override void fileChanged(FileEvent fe) {
                    fire();
                }
                public @Override void fileDataCreated(FileEvent fe) {
                    fire();
                }
                public @Override void fileDeleted(FileEvent fe) {
                    fire();
                }
                private void fire() {
                    synchronized (MavenCoverageProvider.this) {
                        summaryCache = null;
                    }
                    CoverageManager.INSTANCE.resultsUpdated(p, MavenCoverageProvider.this);
                }
            };
            FileUtil.addFileChangeListener(listener, r);
        }
        if (!r.isFile()) {
            LOG.log(Level.FINE, "missing {0}", r);
            return null;
        }
        if (r.length() == 0) {
            // When not previously existent, seems to get created first and written later; file event picks it up when empty.
            LOG.log(Level.FINE, "empty {0}", r);
            return null;
        }
        try {
            // Entity resolver is overriden to prevent retrieval of the cobertura
            // DTDs. The license situation around the DTDs is unclear and as the
            // DTDs don't contain entity definitions, they are not strictly
            // necessary to parse the XML files
            org.w3c.dom.Document report = XMLUtil.parse(new InputSource(r.toURI().toString()), false, false, XMLUtil.defaultErrorHandler(), new EntityResolver() {
                @Override
                public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
                    return new InputSource(new ByteArrayInputStream(new byte[0]));
                }
            });
            LOG.log(Level.FINE, "parsed {0}", r);
            return Pair.of(r, report);
        } catch (/*IO,SAX*/Exception x) {
            LOG.log(Level.INFO, "Could not parse " + r, x);
            return null;
        }
    }

    private ClassPath srcPath() {
        ProjectSourcesClassPathProvider pscp = p.getLookup().lookup(ProjectSourcesClassPathProvider.class);
        assert pscp != null;
        ClassPath cp = pscp.getProjectSourcesClassPath(ClassPath.SOURCE);
        assert cp != null;
        return cp;
    }
    
    public @Override FileCoverageDetails getDetails(final FileObject fo, final Document doc) {
        String path = srcPath().getResourceName(fo);
        if (path == null) {
            return null;
        }
        MavenDetails det = null;
        synchronized (this) {
            MavenSummary summ = summaryCache != null ? summaryCache.get(path) : null;
            if (summ != null) {
                det = summ.getDetails();
                //we have to set the linecount here, as the entire line span is not apparent from the parsed xml, giving strange results then.
                det.lineCount = doc.getDefaultRootElement().getElementCount();
            }
        }
        return det;
    }

    public @Override List<FileCoverageSummary> getResults() {
        Pair<File, org.w3c.dom.Document> r = parse();
        if (r == null) {
            return null;
        }
        ClassPath src = srcPath();
        List<FileCoverageSummary> summs = new ArrayList<FileCoverageSummary>();
        Map<String, MavenSummary> summaries = new HashMap<String, MavenSummary>();
        boolean jacoco = hasPlugin(GROUP_JOCOCO, ARTIFACT_JOCOCO);
        NodeList nl = r.second().getElementsByTagName(jacoco ? "sourcefile" : "class"); // NOI18N
        for (int i = 0; i < nl.getLength(); i++) {
            Element clazz = (Element) nl.item(i);
            String filename;
            List<Element> lines;
            String name;
            if (jacoco) {
                filename = ((Element) clazz.getParentNode()).getAttribute("name") + '/' + clazz.getAttribute("name");
                lines = new ArrayList<Element>();
                for (Element line : XMLUtil.findSubElements(clazz)) {
                    if (line.getTagName().equals("line")) {
                        lines.add(line);
                    }
                }
                name = filename.replaceFirst("[.]java$", "").replace('/', '.');
            } else {
                filename = clazz.getAttribute("filename");
                Element linesE = XMLUtil.findElement(clazz, "lines", null); // NOI18N
                lines = linesE != null ? XMLUtil.findSubElements(linesE) : Collections.<Element>emptyList();
                // XXX nicer to collect together nested classes in same compilation unit
                name = clazz.getAttribute("name").replace('$', '.');
            }
            FileObject java = src.findResource(filename); // NOI18N
            if (java == null) {
                continue;
            }
            final MavenSummary summar = summaryOf(java, name, lines, jacoco, r.first().lastModified());
            summaries.put(filename, summar);
            summs.add(summar);
        }
        synchronized (this) {
            summaryCache = summaries;
        }
        return summs;
    }
    
    private MavenSummary summaryOf(FileObject java, String name, List<Element> lines, boolean jacoco, long lastUpdated) {
        // Not really the total number of lines in the file at all, but close enough - the ones Cobertura recorded.
        int lineCount = 0;
        int executedLineCount = 0;
        Map<Integer, Integer> detLines = new HashMap<Integer, Integer>();
        for (Element line : lines) {
            lineCount++;
            String attr = line.getAttribute(jacoco ? "ci" : "hits");
            String num = line.getAttribute(jacoco ? "nr" : "number");
            detLines.put(Integer.valueOf(num) - 1,Integer.valueOf(attr));
            if (!attr.equals("0")) {
                executedLineCount++;
            }
        }
        MavenDetails det = new MavenDetails(java, lastUpdated, lineCount, detLines);
        MavenSummary s = new MavenSummary(java, name, det, executedLineCount);
        return s;
    }

    public @Override String getTestAllAction() {
        return hasPlugin(GROUP_JOCOCO, ARTIFACT_JOCOCO) ? "jacoco" : "cobertura";
        // XXX and Test button runs COMMAND_TEST_SINGLE on file, which is not good here; cf. CoverageSideBar.testOne
    }

    private static class MavenSummary extends FileCoverageSummary {
        private final MavenDetails details;

        public MavenSummary(FileObject file, String displayName, MavenDetails details, int executedLineCount) {
            super(file, displayName, details.getLineCount(), executedLineCount, 0, 0);
            this.details = details;
            details.setSummary(this);
        }
        
        MavenDetails getDetails() {
            return details;
        }
        
    }
    
    private static class MavenDetails implements FileCoverageDetails {
        private final FileObject fileObject;
        private final long lastUpdated;
        private FileCoverageSummary summary;
        private final Map<Integer, Integer> lineHitCounts;
        int lineCount;

        public MavenDetails(FileObject fileObject, long lastUpdated, int lineCount, Map<Integer, Integer> lineHitCounts) {
            this.fileObject = fileObject;
            this.lastUpdated = lastUpdated;
            this.lineHitCounts = lineHitCounts;
            this.lineCount = lineCount;
        }
        
        
        @Override
        public FileObject getFile() {
            return fileObject;
        }

        @Override
        public int getLineCount() {
            return lineCount;
        }

        @Override
        public boolean hasHitCounts() {
            return true;
        }

        @Override
        public long lastUpdated() {
            return lastUpdated;
        }

        @Override
        public FileCoverageSummary getSummary() {
            return summary;
        }
        public void setSummary(FileCoverageSummary summary) {
            this.summary = summary;
        }

        @Override
        public CoverageType getType(int lineNo) {
            Integer count = lineHitCounts.get(lineNo);
            return count == null ? CoverageType.INFERRED : count == 0 ? CoverageType.NOT_COVERED : CoverageType.COVERED;
        }

        @Override
        public int getHitCount(int lineNo) {
            Integer ret = lineHitCounts.get(lineNo);
            if (ret == null) {
                return 0;
            }
            return ret;
        }
    
    }
}
