/*
 * 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<TestCaseResult>();
        count = 0;
        userErrors = 0;
        internalErrors = 0;
        startTime = -1;
        exDistribution = new HashMap<Class<?>, Integer>();
        stDistribution = new HashMap<TestCaseResult.State, Integer>();
        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) {
                // TODO Auto-generated catch block
                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<Entry<Class<?>, Integer>>(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<Map.Entry<TestCaseResult.State, Integer>>(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;   
    }

}