package com.sleekbyte.tailor.format;

import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import com.sleekbyte.tailor.common.ColorSettings;
import com.sleekbyte.tailor.common.ConfigProperties;
import com.sleekbyte.tailor.common.Messages;
import com.sleekbyte.tailor.output.ViolationMessage;

import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Formatter that displays violation messages in valid HTML output.
 */
public final class HTMLFormatter extends Formatter {

    protected static final String TEMPLATE_PATH = "index.html";
    private static final String NEWLINE_PATTERN = "\n";
    private static final List<Map<String, Object>> FILES = new ArrayList<>();

    public HTMLFormatter(ColorSettings colorSettings) {
        super(colorSettings);
    }

    protected static List<Map<String, Object>> getFiles() {
        return FILES;
    }

    protected static void clearFiles() {
        FILES.clear();
    }

    @Override
    public void displayViolationMessages(List<ViolationMessage> violationMessages, File inputFile) throws IOException {
        List<Map<String, Object>> violations = new ArrayList<>();
        for (ViolationMessage msg : violationMessages) {
            Map<String, Object> violation = new HashMap<>();
            Map<String, Integer> location = new HashMap<>();

            location.put(Messages.LINE_KEY, msg.getLineNumber());
            if (msg.getColumnNumber() != 0) {
                location.put(Messages.COLUMN_KEY, msg.getColumnNumber());
            }
            violation.put(Messages.LOCATION_KEY, location);
            switch (msg.getSeverity()) {
                case ERROR:
                    violation.put(Messages.ERROR, true);
                    break;
                case WARNING:
                    violation.put(Messages.WARNING, true);
                    break;
                default:
                    break;
            }
            violation.put(Messages.RULE_KEY, msg.getRule().getName());
            violation.put(Messages.MESSAGE_KEY, msg.getMessage());

            violations.add(violation);
        }
        storeMessages(violations, true, inputFile.getCanonicalPath());
    }

    @Override
    public void displayParseErrorMessage(File inputFile) throws IOException {
        storeMessages(new ArrayList<>(), false, inputFile.getCanonicalPath());
    }

    @Override
    public void displaySummary(long numFiles, long numSkipped, long numErrors, long numWarnings) throws IOException {
        Map<String, Object> output = new HashMap<>();
        output.put(Messages.SUMMARY_KEY,
            Formatter.formatSummary(numFiles, numSkipped, numErrors, numWarnings).replace(NEWLINE_PATTERN, ""));
        Collections.sort(FILES, Collections.reverseOrder(new Comparator<Map<String, Object>>() {
            @Override
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                return Integer.compare(
                    ((List) o1.get(Messages.VIOLATIONS_KEY)).size(),
                    ((List) o2.get(Messages.VIOLATIONS_KEY)).size()
                );
            }
        }));
        output.put(Messages.FILES_KEY, FILES);
        output.put(Messages.VERSION_LONG_OPT, new ConfigProperties().getVersion());

        Mustache mustache = new DefaultMustacheFactory().compile(
            new InputStreamReader(this.getClass().getResourceAsStream(TEMPLATE_PATH), Charset.defaultCharset()),
            TEMPLATE_PATH
        );
        mustache.execute(new OutputStreamWriter(System.out, Charset.defaultCharset()), output).flush();
    }

    @Override
    public void printProgressInfo(String str) {
        // Not Applicable to this formatter
    }

    private void storeMessages(List<Map<String, Object>> violations, boolean parsed, String filePath)
        throws IOException {
        Map<String, Object> output = new HashMap<>();
        output.put(Messages.PATH_KEY, filePath);
        output.put(Messages.VIOLATIONS_KEY, violations);
        final int numViolations = violations.size();
        output.put(Messages.NUM_VIOLATIONS_KEY,
            Formatter.pluralize(numViolations, Messages.SINGLE_VIOLATION_KEY, Messages.MULTI_VIOLATIONS_KEY)
        );
        output.put(Messages.PARSED_KEY, parsed);
        FILES.add(output);
    }

}

@@ -512,67 +512,8 @@
 st;%0A
-import java.util.Collections;%0Aimport java.util.Comparator;%0A
 impo
@@ -2933,248 +2933,101 @@
     
-Collections.sort(FILES, Collections.reverseOrder(new Comparator%3CMap%3CString, Object%3E%3E() %7B%0A            @Override%0A            public int compare(Map%3CString, Object%3E o1, Map%3CString, Object%3E o2) %7B%0A                return Integer.compare(%0A        
+// Sort files by descending order of the number of violations%0A        FILES.sort((o1, o2) -%3E%0A
     
@@ -3043,17 +3043,17 @@
 (List) o
-1
+2
 .get(Mes
@@ -3085,29 +3085,10 @@
 ze()
-,%0A                  
  
+-
  ((L
@@ -3085,33 +3085,33 @@
 ze() - ((List) o
-2
+1
 .get(Messages.VI
@@ -3135,52 +3135,8 @@
 ze()
-%0A                );%0A            %7D%0A        %7D)
 );%0A 

Simplify sorting of files in HTML format