package edu.hm.hafner.analysis.parser;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;

import org.apache.commons.io.input.BOMInputStream;

import edu.hm.hafner.analysis.Issue;
import edu.hm.hafner.analysis.IssueBuilder;
import edu.hm.hafner.analysis.Priority;
import edu.hm.hafner.util.Ensure;
import static edu.hm.hafner.analysis.assertj.IssueAssert.*;

/**
 * Base class for parser tests. Provides an assertion test for warnings.
 * <p>
 * FIXME: close files
 */
public abstract class ParserTester {
    public static final String WRONG_NUMBER_OF_WARNINGS_DETECTED = "Wrong number of warnings detected: ";
    public static final String DEFAULT_CATEGORY = new IssueBuilder().build().getCategory();

    /**
     * Checks the properties of the specified warning.
     *
     * @param warning    the warning to check
     * @param lineNumber the expected line number
     * @param message    the expected message
     * @param fileName   the expected filename
     * @param category   the expected category
     * @param priority   the expected priority
     */
    protected void checkWarning(final Issue warning, final int lineNumber, final String message, final String fileName, final String category, final Priority priority) {
        assertThat(warning).hasPriority(priority)
                .hasCategory(category)
                .hasLineStart(lineNumber)
                .hasLineEnd(lineNumber)
                .hasMessage(message)
                .hasFileName(fileName);
    }

    /**
     * Checks the properties of the specified warning.
     *
     * @param warning    the warning to check
     * @param lineNumber the expected line number
     * @param column     the expected column
     * @param message    the expected message
     * @param fileName   the expected filename
     * @param category   the expected category
     * @param priority   the expected priority
     */
    protected void checkWarning(final Issue warning, final int lineNumber, final int column, final String message, final String fileName, final String category, final Priority priority) {
        assertThat(warning).hasPriority(priority)
                .hasCategory(category)
                .hasLineStart(lineNumber)
                .hasLineEnd(lineNumber)
                .hasMessage(message)
                .hasFileName(fileName)
                .hasColumnStart(column);
    }

    /**
     * Checks the properties of the specified warning.
     *
     * @param warning    the warning to check
     * @param lineNumber the expected line number
     * @param message    the expected message
     * @param fileName   the expected filename
     * @param type       the expected type
     * @param category   the expected category
     * @param priority   the expected priority
     */
    protected void checkWarning(final Issue warning, final int lineNumber, final String message, final String fileName, final String type, final String category, final Priority priority) {
        assertThat(warning).hasPriority(priority)
                .hasCategory(category)
                .hasLineStart(lineNumber)
                .hasLineEnd(lineNumber)
                .hasMessage(message)
                .hasFileName(fileName)
                .hasType(type);
    }

    /**
     * Checks the properties of the specified warning.
     *
     * @param warning    the warning to check
     * @param lineNumber the expected line number
     * @param column     the expected column
     * @param message    the expected message
     * @param fileName   the expected filename
     * @param type       the expected type
     * @param category   the expected category
     * @param priority   the expected priority
     */
    protected void checkWarning(final Issue warning, final int lineNumber, final int column, final String message, final String fileName, final String type, final String category, final Priority priority) { // NOCHECKSTYLE
        assertThat(warning).hasPriority(priority)
                .hasCategory(category)
                .hasLineStart(lineNumber)
                .hasLineEnd(lineNumber)
                .hasMessage(message)
                .hasFileName(fileName)
                .hasColumnStart(column)
                .hasType(type);
    }

    /**
     * Returns an input stream with the warnings.
     *
     * @return an input stream
     */
    protected Reader openFile() {
        return openFile(getWarningsFile());
    }

    /**
     * Returns an input stream with the warnings.
     *
     * @param fileName the file to read
     * @return an input stream
     */
    protected Reader openFile(final String fileName) {
        try {
            return new InputStreamReader(new BOMInputStream(asStream(fileName)), "UTF-8");
        }
        catch (UnsupportedEncodingException exception) {
            return new InputStreamReader(asStream(fileName));
        }
    }

    private InputStream asStream(final String fileName) {
        InputStream resourceAsStream = ParserTester.class.getResourceAsStream(fileName);

        Ensure.that(resourceAsStream).isNotNull("File %s not found!", fileName);

        return resourceAsStream;
    }

    /**
     * Returns the file name of the warnings file.
     *
     * @return the warnings file name
     */
    protected abstract String getWarningsFile();
}

@@ -1350,32 +1350,33 @@
 iority(priority)
+;
 %0A               
@@ -1364,32 +1364,43 @@
 y);%0A        
-        
+assertThat(warning)
 .hasCategory
@@ -1405,39 +1405,34 @@
 ry(category)
+;
 %0A
-      
         
   .hasLineSt
@@ -1411,34 +1411,51 @@
 egory);%0A        
-  
+assertThat(warning)
 .hasLineStart(li
@@ -1455,32 +1455,33 @@
 tart(lineNumber)
+;
 %0A               
@@ -1469,32 +1469,43 @@
 r);%0A        
-        
+assertThat(warning)
 .hasLineEnd(
@@ -1507,32 +1507,33 @@
 eEnd(lineNumber)
+;
 %0A               
@@ -1521,32 +1521,43 @@
 r);%0A        
-        
+assertThat(warning)
 .hasMessage(
@@ -1556,32 +1556,33 @@
 Message(message)
+;
 %0A               
@@ -1570,32 +1570,43 @@
 e);%0A        
-        
+assertThat(warning)
 .hasFileName
@@ -2230,263 +2230,109 @@
     
-assertThat(warning).hasPriority(priority)%0A                .hasCategory(category)%0A                .hasLineStart(lineNumber)%0A                .hasLineEnd(lineNumber)%0A                .hasMessage(message)%0A                .hasFileName(fileName)%0A                
+checkWarning(warning, lineNumber, message, fileName, category, priority);%0A        assertThat(warning)
 .has
@@ -2964,263 +2964,109 @@
     
-assertThat(warning).hasPriority(priority)%0A                .hasCategory(category)%0A                .hasLineStart(lineNumber)%0A                .hasLineEnd(lineNumber)%0A                .hasMessage(message)%0A                .hasFileName(fileName)%0A                
+checkWarning(warning, lineNumber, message, fileName, category, priority);%0A        assertThat(warning)
 .has
@@ -3768,303 +3768,117 @@
     
-assertThat(warning).hasPriority(priority)%0A                .hasCategory(category)%0A                .hasLineStart(lineNumber)%0A                .hasLineEnd(lineNumber)%0A                .hasMessage(message)%0A                .hasFileName(fileName)%0A                .hasColumnStart(column)%0A                
+checkWarning(warning, lineNumber, column, message, fileName, category, priority);%0A        assertThat(warning)
 .has

Revert "Use fluent API for assertions."