/*
 * 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 internalCount = exDistribution.get(result.error.getClass());
                if (internalCount == null) {
                    internalCount = 0;
                }
                internalCount++;
                exDistribution.put(result.error.getClass(), internalCount);
            }
        }
        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;
    }

}
