package org.junit.rules;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.experimental.results.PrintableResult.testResult;
import static org.junit.experimental.results.ResultMatchers.failureCountIs;
import static org.junit.experimental.results.ResultMatchers.hasSingleFailureContaining;
import static org.junit.experimental.results.ResultMatchers.isSuccessful;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.Description;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;

@SuppressWarnings("deprecation")
public class MethodRulesTest {
    private static boolean ruleWasEvaluated;

    private static class TestMethodRule implements MethodRule {

        public Statement apply(final Statement base, FrameworkMethod method, Object target) {
            return new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    ruleWasEvaluated = true;
                    base.evaluate();
                }
            };
        }
    }

    public static class ExampleTest {
        @Rule
        public MethodRule example = new TestMethodRule();

        @Test
        public void nothing() {
        }
    }

    abstract static class NonPublicExampleTest {
        @Rule
        public MethodRule example = new TestMethodRule();

        @Test
        public void nothing() {
        }
    }

    @Test
    public void ruleIsIntroducedAndEvaluated() {
        ruleWasEvaluated = false;
        assertThat(testResult(ExampleTest.class), isSuccessful());
        assertTrue(ruleWasEvaluated);
    }

    public static class SonOfExampleTest extends ExampleTest {

    }

    @Test
    public void ruleIsIntroducedAndEvaluatedOnSubclass() {
        ruleWasEvaluated = false;
        assertThat(testResult(SonOfExampleTest.class), isSuccessful());
        assertTrue(ruleWasEvaluated);
    }

    public static class SonOfNonPublicExampleTest extends NonPublicExampleTest {

    }

    @Test
    public void ruleIsIntroducedAndEvaluatedOnSubclassOfNonPublicClass() {
        ruleWasEvaluated = false;
        assertThat(testResult(SonOfNonPublicExampleTest.class), isSuccessful());
        assertTrue(ruleWasEvaluated);
    }

    private static int runCount;

    private static class Increment implements MethodRule {
        public Statement apply(final Statement base,
                FrameworkMethod method, Object target) {
            return new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    runCount++;
                    base.evaluate();
                }
            };
        }
    }
    
    public static class MultipleRuleTest {

        @Rule
        public MethodRule incrementor1 = new Increment();

        @Rule
        public MethodRule incrementor2 = new Increment();

        @Test
        public void nothing() {

        }
    }

    @Test
    public void multipleRulesAreRun() {
        runCount = 0;
        assertThat(testResult(MultipleRuleTest.class), isSuccessful());
        assertEquals(2, runCount);
    }

    public static class NoRulesTest {
        public int x;

        @Test
        public void nothing() {

        }
    }

    @Test
    public void ignoreNonRules() {
        assertThat(testResult(NoRulesTest.class), isSuccessful());
    }

    private static String log;

    public static class OnFailureTest {
        @Rule
        public MethodRule watchman = new TestWatchman() {
            @Override
            public void failed(Throwable e, FrameworkMethod method) {
                log += method.getName() + " " + e.getClass().getSimpleName();
            }
        };

        @Test
        public void nothing() {
            fail();
        }
    }

    @Test
    public void onFailure() {
        log = "";
        assertThat(testResult(OnFailureTest.class), failureCountIs(1));
        assertEquals("nothing AssertionError", log);
    }

    public static class WatchmanTest {
        private static String watchedLog;

        @Rule
        public MethodRule watchman = new TestWatchman() {
            @Override
            public void failed(Throwable e, FrameworkMethod method) {
                watchedLog += method.getName() + " "
                        + e.getClass().getSimpleName() + "\n";
            }

            @Override
            public void succeeded(FrameworkMethod method) {
                watchedLog += method.getName() + " " + "success!\n";
            }
        };

        @Test
        public void fails() {
            fail();
        }

        @Test
        public void succeeds() {
        }
    }

    @Test
    public void succeeded() {
        WatchmanTest.watchedLog = "";
        assertThat(testResult(WatchmanTest.class), failureCountIs(1));
        assertThat(WatchmanTest.watchedLog, containsString("fails AssertionError"));
        assertThat(WatchmanTest.watchedLog, containsString("succeeds success!"));
    }

    public static class BeforesAndAfters {
        private static String watchedLog;

        @Before
        public void before() {
            watchedLog += "before ";
        }

        @Rule
        public MethodRule watchman = new TestWatchman() {
            @Override
            public void starting(FrameworkMethod method) {
                watchedLog += "starting ";
            }

            @Override
            public void finished(FrameworkMethod method) {
                watchedLog += "finished ";
            }

            @Override
            public void succeeded(FrameworkMethod method) {
                watchedLog += "succeeded ";
            }
        };

        @After
        public void after() {
            watchedLog += "after ";
        }

        @Test
        public void succeeds() {
            watchedLog += "test ";
        }
    }

    @Test
    public void beforesAndAfters() {
        BeforesAndAfters.watchedLog = "";
        assertThat(testResult(BeforesAndAfters.class), isSuccessful());
        assertThat(BeforesAndAfters.watchedLog, is("starting before test after succeeded finished "));
    }

    public static class WrongTypedField {
        @Rule
        public int x = 5;

        @Test
        public void foo() {
        }
    }

    @Test
    public void validateWrongTypedField() {
        assertThat(testResult(WrongTypedField.class),
                hasSingleFailureContaining("must implement MethodRule"));
    }

    public static class SonOfWrongTypedField extends WrongTypedField {

    }

    @Test
    public void validateWrongTypedFieldInSuperclass() {
        assertThat(testResult(SonOfWrongTypedField.class),
                hasSingleFailureContaining("must implement MethodRule"));
    }

    public static class PrivateRule {
        @Rule
        private TestRule rule = new TestName();

        @Test
        public void foo() {
        }
    }

    @Test
    public void validatePrivateRule() {
        assertThat(testResult(PrivateRule.class),
                hasSingleFailureContaining("must be public"));
    }

    public static class CustomTestName implements TestRule {
        public String name = null;

        public Statement apply(final Statement base, final Description description) {
            return new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    name = description.getMethodName();
                    base.evaluate();
                }
            };
        }
    }

    public static class UsesCustomMethodRule {
        @Rule
        public CustomTestName counter = new CustomTestName();

        @Test
        public void foo() {
            assertEquals("foo", counter.name);
        }
    }

    @Test
    public void useCustomMethodRule() {
        assertThat(testResult(UsesCustomMethodRule.class), isSuccessful());
    }
    
    public static class HasMethodReturningMethodRule {
        private MethodRule methodRule = new MethodRule() {
            public Statement apply(final Statement base, FrameworkMethod method, Object target) {
                return new Statement() {
                    
                    @Override
                    public void evaluate() throws Throwable {
                        ruleWasEvaluated = true;
                        base.evaluate();
                    }
                };
            }
        };
        
        @Rule
        public MethodRule methodRule() {
            return methodRule;
        }
        
        @Test
        public void doNothing() {
            
        }
    }

    /**
     * If there are any public methods annotated with @Rule returning a {@link MethodRule}
     * then it should also be run.
     * 
     * <p>This case has been added with 
     * <a href="https://github.com/junit-team/junit4/issues/589">Issue #589</a> - 
     * Support @Rule for methods works only for TestRule but not for MethodRule
     */
    @Test
    public void runsMethodRuleThatIsReturnedByMethod() {
        ruleWasEvaluated = false;
        assertThat(testResult(HasMethodReturningMethodRule.class), isSuccessful());
        assertTrue(ruleWasEvaluated);
    }
    
    public static class HasMultipleMethodsReturningMethodRule {
        @Rule
        public Increment methodRule1() {
            return new Increment();
        }
        
        @Rule
        public Increment methodRule2() {
            return new Increment();
        }
        
        @Test
        public void doNothing() {
            
        }
    }

    /**
     * If there are multiple public methods annotated with @Rule returning a {@link MethodRule}
     * then all the rules returned should be run.
     * 
     * <p>This case has been added with 
     * <a href="https://github.com/junit-team/junit4/issues/589">Issue #589</a> - 
     * Support @Rule for methods works only for TestRule but not for MethodRule
     */
    @Test
    public void runsAllMethodRulesThatAreReturnedByMethods() {
        runCount = 0;
        assertThat(testResult(HasMultipleMethodsReturningMethodRule.class), isSuccessful());
        assertEquals(2, runCount);
    }
    
    
    public static class CallsMethodReturningRuleOnlyOnce {
        int callCount = 0;
        
        private static class Dummy implements MethodRule {
            public Statement apply(final Statement base, FrameworkMethod method, Object target) {
                return new Statement() {
                    
                    @Override
                    public void evaluate() throws Throwable {
                        base.evaluate();
                    }
                };
            }
        }
       
        
        @Rule
        public MethodRule methodRule() {
            callCount++;
            return new Dummy();
        }
        
        @Test
        public void doNothing() {
            assertEquals(1, callCount);
        }
    }

    /**
     * If there are any public methods annotated with @Rule returning a {@link MethodRule}
     * then method should be called only once.
     * 
     * <p>This case has been added with 
     * <a href="https://github.com/junit-team/junit4/issues/589">Issue #589</a> - 
     * Support @Rule for methods works only for TestRule but not for MethodRule
     */
    @Test
    public void callsMethodReturningRuleOnlyOnce() {
        assertThat(testResult(CallsMethodReturningRuleOnlyOnce.class), isSuccessful());
    }
}
