package org.apache.sling.hc.junitbridge.tests;

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

import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.apache.sling.hc.api.HealthCheck;
import org.apache.sling.hc.api.Result;
import org.apache.sling.hc.junitbridge.HealthCheckTestsProvider;
import org.apache.sling.hc.util.FormattingResultLog;
import org.apache.sling.junit.TestsProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.JUnitCore;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;

/** Test the HealthCheckTestsProvider, which 
 *  uses everything else.
 */
public class HealthCheckTestsProviderTest {
    private TestsProvider provider;
    private long setupTimestamp;
    private final Random random = new Random();
    
    static abstract class HcLogSetter {
        abstract FormattingResultLog setLog(FormattingResultLog log);
    };
    
    private static final Map<String, HcLogSetter> LOG_SETTERS = new HashMap<String, HcLogSetter>(); 
    
    static {
        LOG_SETTERS.put("PASS_HC", new HcLogSetter() {
            @Override
            FormattingResultLog setLog(FormattingResultLog log) {
                log.info("pass");
                return log;
            }
        });
        LOG_SETTERS.put("OK_HC", new HcLogSetter() {
            @Override
            FormattingResultLog setLog(FormattingResultLog log) {
                log.debug("ok");
                return log;
            }
        });
        LOG_SETTERS.put("FAIL_HC", new HcLogSetter() {
            @Override
            FormattingResultLog setLog(FormattingResultLog log) {
                log.warn("fail");
                return log;
            }
        });
        LOG_SETTERS.put("BAD_HC", new HcLogSetter() {
            @Override
            FormattingResultLog setLog(FormattingResultLog log) {
                log.warn("bad");
                return log;
            }
        });
    }
    
    // Our fake tags represent a number of
    // passing (P) or failing (F) fake HCs 
    final String [] TAG_GROUPS = {
            "a,b",
            "some,tags",
            "justOne"
    };
    
    private static String testName(String tagGroup) {
        return HealthCheckTestsProvider.TEST_NAME_PREFIX + tagGroup + HealthCheckTestsProvider.TEST_NAME_SUFFIX;
    }
    
    /** Return ServiceReferences that point to our test HealthChecks */
    private ServiceReference [] getMockReferences(BundleContext bc, String OSGiFilter) {
        
        final List<ServiceReference> refs = new ArrayList<ServiceReference>();
        
        for(String key : LOG_SETTERS.keySet()) {
            if(OSGiFilter.contains(key)) {
                final HcLogSetter hls = LOG_SETTERS.get(key);
                final ServiceReference ref = Mockito.mock(ServiceReference.class);
                Mockito.when(ref.getProperty(Constants.SERVICE_ID)).thenReturn(random.nextLong());
                Mockito.when(ref.getProperty(HealthCheck.NAME)).thenReturn("someTest");
                final HealthCheck hc = new HealthCheck() {
                    @Override
                    public Result execute() {
                        final FormattingResultLog log = new FormattingResultLog();
                        return new Result(hls.setLog(log));
                    }
                };
                Mockito.when(bc.getService(ref)).thenReturn(hc);
                
                refs.add(ref);
            }
        }
        
        return refs.toArray(new ServiceReference[]{});
    }
            
    @Before
    public void setup() throws InvalidSyntaxException {
        setupTimestamp = System.currentTimeMillis();
        final ComponentContext ctx = Mockito.mock(ComponentContext.class);

        // context properties
        final Dictionary<String, Object> props = new Hashtable<String, Object>();
        props.put(HealthCheckTestsProvider.PROP_TAG_GROUPS, TAG_GROUPS);
        props.put(Constants.SERVICE_PID, getClass().getName());
        Mockito.when(ctx.getProperties()).thenReturn(props);
        
        // bundle context
        final BundleContext bc = Mockito.mock(BundleContext.class);
        Mockito.when(ctx.getBundleContext()).thenReturn(bc);
        
        // HealthCheck ServiceReferences mocks
        Mockito.when(bc.getServiceReferences(Mockito.anyString(), Mockito.anyString())).thenAnswer(
            new Answer<ServiceReference[]> () {
                @Override
                public ServiceReference[] answer(InvocationOnMock invocation) throws Throwable {
                    return getMockReferences(bc, (String)invocation.getArguments()[1]);
                }
            });
        
        provider = new HealthCheckTestsProvider() {
            {
                activate(ctx);
            }
        };
    }
    
    @Test
    public void testGetTestNames() {
        final List<String> names = provider.getTestNames();
        assertEquals(TAG_GROUPS.length, names.size());
        for(String tag : TAG_GROUPS) {
            final String expected = testName(tag);
            assertTrue("Expecting test names to contain " + expected + ", " + names, names.contains(expected));
        }
    }
    
    @Test
    public void testServicePid() {
        assertEquals(getClass().getName(), provider.getServicePid());
    }
    
    @Test
    public void testLastModified() {
        assertTrue(provider.lastModified() >= setupTimestamp);
    }
    
    @Test
    public void testNoFailuresHealthCheck() throws ClassNotFoundException {
        final Class<?> c = provider.createTestClass(testName("PASS_HC"));
        assertNotNull("Expecting non-null test class", c);
        final org.junit.runner.Result r = JUnitCore.runClasses(c); 
        assertEquals(0, r.getFailureCount());
        assertEquals(1, r.getRunCount());
    }
    
    @Test
    public void testFailingHealthCheck() throws ClassNotFoundException {
        final Class<?> c = provider.createTestClass(testName("FAIL_HC and BAD_HC"));
        assertNotNull("Expecting non-null test class", c);
        final org.junit.runner.Result r = JUnitCore.runClasses(c); 
        assertEquals(2, r.getFailureCount());
        assertEquals(2, r.getRunCount());
    }
    
    @Test
    public void testPassAndFailHealthCheck() throws ClassNotFoundException {
        final Class<?> c = provider.createTestClass(testName("FAIL_HC and PASS_HC and OK_HC and BAD_HC"));
        assertNotNull("Expecting non-null test class", c);
        final org.junit.runner.Result r = JUnitCore.runClasses(c); 
        assertEquals(2, r.getFailureCount());
        assertEquals(4, r.getRunCount());
    }

    @Test(expected=RuntimeException.class)
    public void testInvalidTestName() throws ClassNotFoundException {
        provider.createTestClass("foo");
    }
}