package com.sleekbyte.tailor.output;

import com.sleekbyte.tailor.common.Location;
import com.sleekbyte.tailor.common.Messages;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

/**
 * Generates and outputs formatted analysis messages for Xcode
 */
public class Printer implements AutoCloseable {

    private File inputFile;
    private Set<String> msgBuffer = new HashSet<>();

    public Printer(File inputFile) {
        this.inputFile = inputFile;
    }

    /**
     * Prints warning message
     *
     * @param warningMsg warning message to print
     * @param location   location object containing line and column number for printing
     */
    public void warn(String warningMsg, Location location) {
        print(Messages.WARNING, warningMsg, location);
    }

    /**
     * Prints error message
     *
     * @param errorMsg error message to print
     * @param location location object containing line and column number for printing
     */
    public void error(String errorMsg, Location location) {
        print(Messages.ERROR, errorMsg, location);
    }

    private void print(String classification, String msg, Location location) {
        String outputString = "";
        try {
            String column = (location.column != 0) ? (":" + location.column) : "";
            outputString = this.inputFile.getCanonicalPath() + ":" + location.line + column + ": " +
                    classification + ": " + msg;
        } catch (IOException e) {
            System.err.println("Error in getting canonical path of input file: " + e.getMessage());
        }
        this.msgBuffer.add(outputString);
    }

    // Visible for testing only
    public static String genOutputStringForTest(String filePath, int line, String classification,
                                                String msg) {
        return filePath + ":" + line + ": " + classification + ": " + msg;
    }

    // Visible for testing only
    public static String genOutputStringForTest(String filePath, int line, int column, String classification,
                                                String msg) {
        return filePath + ":" + line + ":" + column + ": " + classification + ": " + msg;
    }

    @Override
    public void close() {
        // TODO: #55: this.msgBuffer.sort(lineNumber1 < lineNumber2, columnNumber1 < columnNumber2);
        this.msgBuffer.forEach(System.out::println);
        this.msgBuffer.clear();
    }

    public class ViolationMessage implements Comparable<ViolationMessage> {
        private final String filePath;
        private final int lineNumber;
        private final int columnNumber;
        private final String classification;
        private final String violationMessage;

        public ViolationMessage(String filePath, int lineNumber, int columnNumber, String classification, String violationMessage) {
            this.filePath = filePath;
            this.lineNumber = lineNumber;
            this.columnNumber = columnNumber;
            this.classification = classification;
            this.violationMessage = violationMessage;
        }

        @Override
        public int compareTo(final ViolationMessage message) {
            return 0;
        }

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof ViolationMessage)) {
                return false;
            }
            ViolationMessage message;
            message = (ViolationMessage)o;
            return this.filePath == message.filePath
                    && this.lineNumber == message.lineNumber
                    && this.columnNumber == message.lineNumber
                    && this.classification == message.classification
                    && this.violationMessage == message.violationMessage;
        }

        public String toString() {
            return String.format("%s:%d:%d: %s: %s", this.filePath, this.lineNumber, this.columnNumber, this.classification, this.violationMessage);
        }
    }
}

@@ -192,18 +192,67 @@
 til.Hash
-Se
+Map;%0Aimport java.util.HashSet;%0Aimport java.util.Lis
 t;%0Aimpor
@@ -433,44 +433,90 @@
 ate 
-Set%3CString%3E msgBuffer = new HashSet%3C
+HashMap%3CString, ViolationMessage%3E msgBuffer = new HashMap%3CString, ViolationMessage
 %3E();
@@ -1303,32 +1303,48 @@
     
-String outputString = %22%22
+ViolationMessage violationMessage = null
 ;%0A  
@@ -1454,97 +1454,185 @@
     
-outputString = this.inputFile.getCanonicalPath() + %22:%22 + location.line + column + %22: %22 +%0A
+violationMessage = new ViolationMessage(this.inputFile.getCanonicalPath(),%0A                                location.line,%0A                                location.column,%0A      
     
@@ -1647,16 +1647,22 @@
         
+      
 classifi
@@ -1663,39 +1663,65 @@
 assification
- + %22: %22 +
+,%0A                               
  msg
+)
 ;%0A
+%0A
         %7D ca
@@ -1879,24 +1879,57 @@
 fer.
-add(outputString
+put(violationMessage.toString(), violationMessage
 );%0A 
@@ -2658,30 +2658,90 @@
         
-this.msgBuffer
+Set%3CString%3E msgBufferKeys = this.msgBuffer.keySet();%0A        msgBufferKeys
 .forEach
@@ -3562,17 +3562,67 @@
  return 
-0
+this.filePath.compareToIgnoreCase(message.filePath)
 ;%0A      

Use hashmap to store violation messages