/*
 * Tanaguru - Automated webpage assessment
 * Copyright (C) 2008-2011  Open-S Company
 *
 * This file is part of Tanaguru.
 *
 * Tanaguru is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contact us by mail: open-s AT open-s DOT com
 */
package org.opens.maven.plugins.kbcsv;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.jaxen.JaxenException;
import org.jaxen.XPath;
import org.jaxen.jdom.JDOMXPath;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 *
 * @author Vivien Barousse
 * @goal generate
 */
public class KbCsvMojo extends AbstractMojo {

    private static final String[] KB_TEST_RESULTS = {"Failed",
        "Passed",
        "NA",
        "NMI"};

    private static final String[] TG_TEST_RESULTS = {"FAILED",
        "PASSED",
        "NOT_APPLICABLE",
        "NEED_MORE_INFO"};

    /**
     * @parameter default-value="http://www.kbaccess.org/kba/"
     */
    private String baseUrl;

    /**
     * @parameter
     */
    private File inCsv;

    /**
     * @parameter default-value="target/csv/out.csv"
     */
    private File outCsv;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        try {
            FileReader fin = new FileReader(inCsv);
            BufferedReader reader = new BufferedReader(fin);

            if (!outCsv.getParentFile().exists()) {
                outCsv.getParentFile().mkdirs();
            }
            PrintWriter writer = new PrintWriter(outCsv);
            writer.println(formatCsvLine("name", "url", "campain", "test", "result"));

            String readed;
            while ((readed = reader.readLine()) != null) {
                String[] params = readed.split(";"); // CSV params: 0=campain, 1=test

                if (params.length != 2) {
                    getLog().warn("Incorrect line: " + readed);
                    continue;
                }
                
                String ruleUrl = baseUrl + params[0] + "/" + params[1] + "/";
                for (int i = 0; i < KB_TEST_RESULTS.length; i++) {
                    String url = ruleUrl + KB_TEST_RESULTS[i]+"/";

                    try {
                        for (String result : getUrls(url)) {
                            String targetName = sanitizeClassName(result.substring(28)); // Substring 28 to remove URL beginning
                            writer.println(formatCsvLine(targetName, result, params[0], params[1], TG_TEST_RESULTS[i]));
                        }
                    } catch (JaxenException ex) {
                        getLog().warn("Unable to select URLs for address " + url, ex);
                    } catch (JDOMException ex) {
                        getLog().warn("Invalid XML at " + url, ex);
                    }
                }
            }

            writer.close();
            reader.close();
            fin.close();
        } catch (IOException ex) {
            throw new MojoExecutionException("Unexpected IO Exception", ex);
        }
    }

    private String formatCsvLine(String... args) {
        boolean first = true;
        StringBuilder builder = new StringBuilder();
        for (String arg : args) {
            if (!first) {
                builder.append(";");
            } else {
                first = false;
            }

            builder.append(arg);
        }

        return builder.toString();
    }

    private String sanitizeClassName(String unsafe) {
        return unsafe.replaceAll("[^0-9A-Za-z_]+", "_");
    }

    private List<String> getUrls(String url) throws JDOMException, JaxenException, IOException {
        SAXBuilder builder = new SAXBuilder();
        EntityResolver resolver = new XhtmlEntityResolver();
        builder.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
        builder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
        builder.setEntityResolver(resolver);
        Document document = builder.build(new URL(url));
        XPath xpath = new JDOMXPath("//*[@id='resultat']//*[@href]/@href");
        List<Attribute> results = xpath.selectNodes(document);
        List<String> urls = new ArrayList<String>();
        for (Attribute attr : results) {
            urls.add(attr.getValue());
        }
        return urls;
    }

    private class XhtmlEntityResolver implements EntityResolver {

        @Override
        public InputSource resolveEntity(String publicId, String systemId)
                throws SAXException, IOException {

                if (systemId.equals("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd")) {
                    InputSource source = new InputSource(getClass().getResourceAsStream("/dtd/xhtml1-strict.dtd"));
                    source.setPublicId(publicId);
                    source.setSystemId(systemId);
                    return source;
                }

            return null;
        }

    }

}

@@ -899,126 +899,9 @@
 .io.
-BufferedReader;%0Aimport java.io.File;%0Aimport java.io.FileReader;%0Aimport java.io.IOException;%0Aimport java.io.PrintWriter
+*
 ;%0Aim
@@ -3080,16 +3080,24 @@
 TS%5Bi%5D+%22/
+?lang=en
 %22;%0A%0A    

use english version of kbaccess to avoid special characters in returned page