package me.atam.atam4j;

import me.atam.atam4jdomain.IndividualTestResult;
import me.atam.atam4jdomain.TestsRunResult;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class TestRunListener extends RunListener{

    private Map<TestIdentifier, IndividualTestResult> individualTestReportMap;
    private boolean testsFinished = false;


    @Override
    public void testRunStarted(Description description) throws Exception {
        individualTestReportMap =  new HashMap<>();
    }

    @Override
    public void testStarted(Description description) throws Exception {
        individualTestReportMap.put(
                new TestIdentifier(description),
                new IndividualTestResult(description.getClassName(), description.getMethodName(), true)
        );
    }

    @Override
    public void testFailure(Failure failure) throws Exception {
        IndividualTestResult individualTestResult = new IndividualTestResult(
                failure.getDescription().getClassName(),
                failure.getDescription().getMethodName(),
                false
        );
        individualTestReportMap.put(new TestIdentifier(failure.getDescription()), individualTestResult);
    }

    public TestsRunResult getTestRunResult() {
        if (!testsFinished) {
            return new TestsRunResult(TestsRunResult.Status.TOO_EARLY);
        }
        return new TestsRunResult(individualTestReportMap.values());
    }

    @Override
    public void testRunFinished(Result result) throws Exception {
        this.testsFinished = true;
    }

    private static class TestIdentifier{
        private Class testClass;
        private String testName;

        public TestIdentifier(Description description) {
            this.testClass = description.getTestClass();
            this.testName = description.getMethodName();
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            TestIdentifier that = (TestIdentifier) o;
            return Objects.equals(testClass, that.testClass) &&
                    Objects.equals(testName, that.testName);
        }

        @Override
        public int hashCode() {
            return Objects.hash(testClass, testName);
        }
    }
}

@@ -277,16 +277,106 @@
 stener;%0A
+import org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A%0Aimport java.lang.reflect.Method;
 %0Aimport 
@@ -494,16 +494,105 @@
 tener%7B%0A%0A
+    private static final Logger LOGGER = LoggerFactory.getLogger(TestRunListener.class);%0A
     priv
@@ -933,32 +933,33 @@
 ows Exception %7B%0A
+%0A
         individu
@@ -1069,16 +1069,41 @@
 tResult(
+%0A                        
 descript
@@ -1121,16 +1121,40 @@
 sName(),
+%0A                       
  descrip
@@ -1174,16 +1174,94 @@
 dName(),
+%0A                        getCategoryName(description),%0A                       
  true)%0A 
@@ -1407,21 +1407,17 @@
 esult = 
-new I
+i
 ndividua
@@ -1427,264 +1427,111 @@
 stRe
-sult(%0A                failure.getDescription().getClassName(),%0A                failure.getDescription().getMethodName(),%0A                false%0A        );%0A        individualTestReportMap.put(new TestIdentifier(failure.getDescription()), individualTestResult
+portMap.get(new TestIdentifier(failure.getDescription()));%0A        individualTestResult.setPassed(false
 );%0A 
@@ -1889,24 +1889,705 @@
 rue;%0A    %7D%0A%0A
+    private String getCategoryName(Description description) %7B%0A%0A        String category = %22default%22;%0A%0A        try %7B%0A            Class testClass = Class.forName(description.getClassName());%0A            Method testMethod = testClass.getMethod(description.getMethodName());%0A            if (testMethod.isAnnotationPresent(MonitorCategory.class)) %7B%0A                MonitorCategory monitorCategory = testMethod.getAnnotation(MonitorCategory.class);%0A                category = monitorCategory.name();%0A            %7D%0A        %7D catch (ClassNotFoundException %7C NoSuchMethodException e) %7B%0A            LOGGER.warn(%22Test class or method not found%22, e);%0A        %7D%0A%0A        return category;%0A    %7D%0A%0A
     private 

Add category field to `IndividualTestResult`