/*
 * 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.vxquery.xtest;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.vxquery.xtest.TestCaseResult.State;

public class HTMLFileReporterImpl implements ResultReporter {
    private List<TestCaseResult> results;

    private int count;

    private int userErrors;

    private int internalErrors;

    private Map<Class<?>, Integer> exDistribution;

    private Map<TestCaseResult.State, Integer> stDistribution;

    private long startTime;

    private long endTime;

    private PrintWriter out;

    private File reportFile;

    public HTMLFileReporterImpl(File file) {
        results = new ArrayList<>();
        count = 0;
        userErrors = 0;
        internalErrors = 0;
        startTime = -1;
        exDistribution = new HashMap<>();
        stDistribution = new HashMap<>();
        reportFile = file;
    }

    @Override
    public void reportResult(TestCaseResult result) {
        results.add(result);
        endTime = System.currentTimeMillis();
        if (startTime < 0) {
            startTime = endTime;
        }
        if (result.error()) {
            if (result.userError()) {
                ++userErrors;
            } else {
                ++internalErrors;
                Integer count = exDistribution.get(result.error.getClass());
                if (count == null) {
                    count = 0;
                }
                count++;
                exDistribution.put(result.error.getClass(), count);
            }
        }
        Integer stCount = stDistribution.get(result.state);
        if (stCount == null) {
            stCount = 0;
        }
        stCount++;
        stDistribution.put(result.state, stCount);
        ++count;
    }

    @Override
    public void close() {
        if (reportFile != null) {
            try {
                out = new PrintWriter(reportFile);
                writeHTML(out, createResultDir(reportFile));
                out.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static File createResultDir(File file) {
        String fileName = file.getName();
        int dot = file.getName().lastIndexOf('.');
        String resultDirName = (dot < 0 ? fileName : fileName.substring(0, dot)) + "_results";
        return file.getParent() != null ? new File(file.getParent() + File.separator + resultDirName)
                : new File(resultDirName);
    }

    public void writeHTML(PrintWriter out) {
        writeHTML(out, null);
    }

    public void writeHTML(PrintWriter out, File resultDir) {
        long start = System.currentTimeMillis();
        out.println("<html><body>");
        writeSummary(out, count, userErrors, internalErrors, startTime, endTime);
        out.println("<hl>");
        writeStateDistribution(out, stDistribution);
        out.println("<hl>");
        writeExceptionDistribution(out, exDistribution);
        out.println("<hl>");
        writeResults(out, resultDir, results);
        out.println("</body></html>");
        System.err.println("HTML generation time: " + (System.currentTimeMillis() - start));
    }

    private static void writeSummary(PrintWriter out, int count, int userErrors, int internalErrors, long startTime,
            long endTime) {
        out.println("<table>");
        out.println("<tr><td>Test Count</td><td>");
        out.println(count);
        out.println("</td></tr>");
        out.println("<tr><td>Test Errors</td><td>");
        out.println(userErrors);
        out.println("</td></tr>");
        out.println("<tr><td>Test Failures</td><td>");
        out.println(internalErrors);
        out.println("</td></tr>");
        out.println("<tr><td>Total time</td><td>");
        out.println(endTime - startTime);
        out.println("</td></tr>");
        out.println("</table>");
    }

    private static void writeExceptionDistribution(PrintWriter out, Map<Class<?>, Integer> exDistribution) {
        out.println("<table>");
        List<Entry<Class<?>, Integer>> entryList = new ArrayList<>(exDistribution.entrySet());
        Comparator<Entry<Class<?>, Integer>> comp = new Comparator<Entry<Class<?>, Integer>>() {
            public int compare(Entry<Class<?>, Integer> o1, Entry<Class<?>, Integer> o2) {
                return o1.getKey().getName().compareTo(o2.getKey().getName());
            }
        };
        Collections.sort(entryList, comp);
        for (Map.Entry<Class<?>, Integer> e : entryList) {
            out.println("<tr><td>");
            out.println(e.getKey().getName());
            out.println("</td><td>");
            out.println(e.getValue());
            out.println("</td></tr>");
        }
        out.println("</table>");
    }

    private static void writeStateDistribution(PrintWriter out, Map<TestCaseResult.State, Integer> stDistribution) {
        out.println("<table>");
        List<Map.Entry<TestCaseResult.State, Integer>> entryList = new ArrayList<>(stDistribution.entrySet());
        Comparator<Map.Entry<TestCaseResult.State, Integer>> comp = new Comparator<Map.Entry<TestCaseResult.State, Integer>>() {
            public int compare(Map.Entry<TestCaseResult.State, Integer> o1,
                    Map.Entry<TestCaseResult.State, Integer> o2) {
                return o1.getKey().compareTo(o2.getKey());
            }
        };
        Collections.sort(entryList, comp);
        for (Map.Entry<TestCaseResult.State, Integer> e : entryList) {
            State key = e.getKey();
            out.print("<tr style=\"background: ");
            out.println(key.getColor());
            out.println(";\"><td>");
            out.println(key);
            out.println("</td><td>");
            out.println(e.getValue());
            out.println("</td></tr>");
        }
        out.println("</table>");
    }

    private static void writeResults(PrintWriter out, File resultDir, List<TestCaseResult> results) {
        ResultManager rfw = new ResultManager(resultDir);
        out.println("<table>");
        int len = results.size();
        for (int i = 0; i < len; ++i) {
            TestCaseResult res = results.get(i);
            out.print("<tr style=\"background: ");
            out.println(res.state.getColor());
            out.println(";\"><td>");
            out.print(i + 1);
            out.print("</td><td><a href=\"");
            out.print(res.testCase.getXQueryFile().toURI());
            out.print("\">");
            String queryDisplayName = res.testCase.getXQueryDisplayName();
            out.print(queryDisplayName);
            out.print("</a></td><td>");
            out.print(res.time);
            out.print("</td><td>");
            String uri = rfw.writeResult(res, queryDisplayName);
            if (uri != null) {
                out.print("<a href=\"");
                out.print(uri);
                out.print("\">");
                out.print(res.report);
                out.print("</a>");
            } else {
                out.print(res.report);
            }
            out.println("</td></tr>");
        }
        out.println("</table>");
        rfw.close();
    }

}

/**
 * writes results into several HTML files of manageable size
 */
class ResultManager {

    /**
     * if the length of a file passes this length, a new file will be used
     * for the next result
     */
    private static final long MAX_LEN = 1000000;

    private final File dir;

    private File curFile;
    private URI curURI;
    private FileWriter curFileWriter;
    private PrintWriter curPrintWriter;

    ResultManager(File dir) {
        this.dir = dir;
    }

    /**
     * writes an HTML serialization of a test result into a temp HTML file
     * inside the given directory
     *
     * @param res
     *            the result data for 1 test case
     * @param linkName
     *            the name of the (internal) HTML link that points to
     *            the test result inside the HTML file
     * @return the full URI that references the test result in the HTML file
     */
    String writeResult(TestCaseResult res, String linkName) {
        if (dir == null) {
            return null;
        }
        try {
            if (curFile == null || curFile.length() > MAX_LEN) {
                if (curFile != null) {
                    writeDocFooter(curPrintWriter);
                    curPrintWriter.flush();
                    curFileWriter.close();
                } else {
                    ensureDir(dir);
                }
                curFile = File.createTempFile("res", ".html", dir);
                curFileWriter = new FileWriter(curFile);
                curPrintWriter = new PrintWriter(new BufferedWriter(curFileWriter));
                curURI = curFile.toURI();
                writeDocHeader(curPrintWriter);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        curPrintWriter.println("<a style=\"background: " + res.state.getColor() + "\" name=\"" + linkName
                + "\">&nbsp;&nbsp;&nbsp;</a>");
        curPrintWriter.println(linkName);
        curPrintWriter.println("<pre>");
        if (res.result != null) {
            curPrintWriter.println(escape(res.result));
        } else {
            res.error.printStackTrace(curPrintWriter);
        }
        curPrintWriter.println("</pre>");
        return curURI + "#" + linkName;
    }

    void close() {
        try {
            if (curFile != null) {
                writeDocFooter(curPrintWriter);
                curPrintWriter.flush();
                curFileWriter.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void ensureDir(File dir) throws IOException {
        if (!dir.isDirectory() && !dir.mkdirs()) {
            throw new IOException("could not create dir " + dir);
        }
    }

    private static void writeDocHeader(PrintWriter resOut) {
        resOut.println("<html><head><title>results</title>");
        resOut.println("<style type=\"text/css\">");
        resOut.println("pre {background: #F0F0F0}");
        resOut.println("</style></head><body>");
    }

    private static void writeDocFooter(PrintWriter resOut) {
        resOut.println("</body></html>");
    }

    /* this should not be necessary anymore, when the XQuery serialization
     * works right
     */
    private static String escape(String s) {
        final char[] ca = s.toCharArray();
        final int l = ca.length;
        int start = 0;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < l; ++i) {
            switch (ca[i]) {
                case '<':
                    sb.append(ca, start, i - start);
                    sb.append("&lt;");
                    start = i + 1;
                    break;
                case '>':
                    sb.append(ca, start, i - start);
                    sb.append("&gt;");
                    start = i + 1;
                    break;
                case '&':
                    sb.append(ca, start, i - start);
                    sb.append("&amp;");
                    start = i + 1;
                    break;
            }
        }
        return start > 0 ? sb.toString() : s;
    }

}
