package com.sleekbyte.tailor.output;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import com.sleekbyte.tailor.common.Location;
import com.sleekbyte.tailor.common.Rules;
import com.sleekbyte.tailor.common.Severity;
import com.sleekbyte.tailor.format.Formatter;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * Tests for {@link Printer}.
 */
@RunWith(MockitoJUnitRunner.class)
public class PrinterTest {

    static class MockFormatter implements Formatter {
        boolean displayViolationMessagesCalled = false;
        boolean displayParseErrorMessageCalled = false;

        public void reset() {
            displayParseErrorMessageCalled = false;
            displayParseErrorMessageCalled = false;
        }

        @Override
        public void displayViolationMessages(List<ViolationMessage> violationMessages) throws IOException {
            displayViolationMessagesCalled = true;
        }

        @Override
        public void displayParseErrorMessage() throws IOException {
            displayParseErrorMessageCalled = true;
        }
    }

    private static final String WARNING_MSG = "this is a warning";
    private static final String ERROR_MSG = "this is an error";
    private static final int LINE_NUMBER = 23;
    private static final int COLUMN_NUMBER = 13;

    private File inputFile = new File("abc.swift");
    private MockFormatter formatter = new MockFormatter();
    private Printer printer = new Printer(inputFile, Severity.ERROR, formatter);
    private Printer warnPrinter = new Printer(inputFile, Severity.WARNING, formatter);

    @After
    public void tearDown() throws IOException {
        formatter.reset();
    }

    @Test
    public void testFormatterDisplayMessage() throws IOException {
        printer.error(Rules.LOWER_CAMEL_CASE, ERROR_MSG, new Location(LINE_NUMBER, COLUMN_NUMBER));
        printer.close();
        assertTrue(formatter.displayViolationMessagesCalled);
        assertFalse(formatter.displayParseErrorMessageCalled);
    }

    @Test
    public void testFormatterParseErrorMessage() throws IOException {
        printer.printParseErrorMessage();
        assertFalse(formatter.displayViolationMessagesCalled);
        assertTrue(formatter.displayParseErrorMessageCalled);
    }

    @Test
    public void testError() throws IOException {
        printer.error(Rules.LOWER_CAMEL_CASE, ERROR_MSG, new Location(LINE_NUMBER, COLUMN_NUMBER));
        ViolationMessage message = printer.getViolationMessages().get(0);
        assertEquals(message.getSeverity(), Severity.ERROR);
        validateViolationMessage(message, Rules.LOWER_CAMEL_CASE, ERROR_MSG, LINE_NUMBER,
            COLUMN_NUMBER);
        printer.close();
    }

    @Test
    public void testWarn() throws IOException {
        printer.warn(Rules.LOWER_CAMEL_CASE, WARNING_MSG, new Location(LINE_NUMBER, COLUMN_NUMBER));
        ViolationMessage message = printer.getViolationMessages().get(0);
        assertEquals(message.getSeverity(), Severity.WARNING);
        validateViolationMessage(message, Rules.LOWER_CAMEL_CASE, WARNING_MSG, LINE_NUMBER,
            COLUMN_NUMBER);
        printer.close();
    }

    @Test
    public void testWarnWithLocationSuccess() throws IOException {
        printer.warn(Rules.LOWER_CAMEL_CASE, WARNING_MSG, new Location(LINE_NUMBER, COLUMN_NUMBER));
        ViolationMessage message = printer.getViolationMessages().get(0);
        assertEquals(Severity.WARNING, message.getSeverity());
        printer.close();
    }

    @Test
    public void testErrorWithLocationSuccess() throws IOException {
        printer.error(Rules.LOWER_CAMEL_CASE, ERROR_MSG, new Location(LINE_NUMBER, COLUMN_NUMBER));
        ViolationMessage message = printer.getViolationMessages().get(0);
        assertEquals(Severity.ERROR, message.getSeverity());
        printer.close();
    }

    @Test
    public void testErrorWithMaxSeverityWarn() throws IOException {
        warnPrinter.error(Rules.LOWER_CAMEL_CASE, ERROR_MSG, new Location(LINE_NUMBER, COLUMN_NUMBER));
        ViolationMessage message = warnPrinter.getViolationMessages().get(0);
        assertEquals(Severity.WARNING, message.getSeverity());
        warnPrinter.close();
    }

    @Test
    public void testWarnWithMaxSeverityWarn() throws IOException {
        warnPrinter.warn(Rules.LOWER_CAMEL_CASE, WARNING_MSG, new Location(LINE_NUMBER, COLUMN_NUMBER));
        ViolationMessage message = warnPrinter.getViolationMessages().get(0);
        assertEquals(Severity.WARNING, message.getSeverity());
        warnPrinter.close();
    }

    private void validateViolationMessage(ViolationMessage message, Rules rule, String msg,
                                             int line, int column) {
        assertEquals(rule, message.getRule());
        assertEquals(msg, message.getMessage());
        assertEquals(line, message.getLineNumber());
        assertEquals(column, message.getColumnNumber());
    }

}

@@ -346,32 +346,8 @@
 er;%0A
-import org.junit.After;%0A
 impo
@@ -791,153 +791,8 @@
 e;%0A%0A
-        public void reset() %7B%0A            displayParseErrorMessageCalled = false;%0A            displayParseErrorMessageCalled = false;%0A        %7D%0A%0A
     
@@ -1641,101 +1641,8 @@
 );%0A%0A
-    @After%0A    public void tearDown() throws IOException %7B%0A        formatter.reset();%0A    %7D%0A%0A
     

Remove reset method