/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.cxf.dosgi.dsw.service;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import org.apache.cxf.dosgi.dsw.api.DistributionProvider;
import org.apache.cxf.dosgi.dsw.api.Endpoint;
import org.apache.cxf.dosgi.dsw.handlers.CXFDistributionProvider;
import org.apache.cxf.dosgi.dsw.handlers.HttpServiceManager;
import org.apache.cxf.dosgi.dsw.handlers.ServerWrapper;
import org.apache.cxf.dosgi.dsw.qos.DefaultIntentMapFactory;
import org.apache.cxf.dosgi.dsw.qos.IntentManager;
import org.apache.cxf.dosgi.dsw.qos.IntentManagerImpl;
import org.apache.cxf.dosgi.dsw.qos.IntentMap;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.easymock.IMocksControl;
import org.junit.Test;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.remoteserviceadmin.EndpointDescription;
import org.osgi.service.remoteserviceadmin.ExportRegistration;
import org.osgi.service.remoteserviceadmin.ImportRegistration;
import org.osgi.service.remoteserviceadmin.RemoteConstants;

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

@SuppressWarnings({
    "rawtypes", "unchecked"
   })
public class RemoteServiceAdminCoreTest {

    @Test
    public void testDontExportOwnServiceProxies() throws InvalidSyntaxException {
        IMocksControl c = EasyMock.createControl();
        Bundle b = c.createMock(Bundle.class);
        BundleContext bc = c.createMock(BundleContext.class);

        EasyMock.expect(bc.getBundle()).andReturn(b).anyTimes();
        bc.addServiceListener(EasyMock.<ServiceListener>anyObject(), EasyMock.<String>anyObject());
        EasyMock.expectLastCall().anyTimes();
        bc.removeServiceListener(EasyMock.<ServiceListener>anyObject());
        EasyMock.expectLastCall().anyTimes();

        Dictionary<String, String> d = new Hashtable<String, String>();
        EasyMock.expect(b.getHeaders()).andReturn(d).anyTimes();

        ServiceReference sref = c.createMock(ServiceReference.class);
        EasyMock.expect(sref.getBundle()).andReturn(b).anyTimes();
        EasyMock.expect(sref.getPropertyKeys())
            .andReturn(new String[]{"objectClass", "service.exported.interfaces"}).anyTimes();
        EasyMock.expect(sref.getProperty("objectClass")).andReturn(new String[] {"a.b.C"}).anyTimes();
        EasyMock.expect(sref.getProperty(RemoteConstants.SERVICE_IMPORTED)).andReturn(true).anyTimes();
        EasyMock.expect(sref.getProperty("service.exported.interfaces")).andReturn("*").anyTimes();

        DistributionProvider provider = c.createMock(DistributionProvider.class);

        c.replay();

        RemoteServiceAdminCore rsaCore = new RemoteServiceAdminCore(bc, provider);

        // must return an empty List as sref if from the same bundle
        List<ExportRegistration> exRefs = rsaCore.exportService(sref, null);

        assertNotNull(exRefs);
        assertEquals(0, exRefs.size());

        // must be empty
        assertEquals(rsaCore.getExportedServices().size(), 0);

        c.verify();
    }

    @Test
    public void testImport() {
        IMocksControl c = EasyMock.createNiceControl();
        Bundle b = c.createMock(Bundle.class);
        BundleContext bc = c.createMock(BundleContext.class);

        Dictionary<String, String> d = new Hashtable<String, String>();
        EasyMock.expect(b.getHeaders()).andReturn(d).anyTimes();

        EasyMock.expect(bc.getBundle()).andReturn(b).anyTimes();
        EasyMock.expect(b.getSymbolicName()).andReturn("BundleName").anyTimes();

        Map<String, Object> p = new HashMap<String, Object>();
        p.put(RemoteConstants.ENDPOINT_ID, "http://google.de");
        p.put(Constants.OBJECTCLASS, new String[] {
            "es.schaaf.my.class"
        });
        p.put(RemoteConstants.SERVICE_IMPORTED_CONFIGS, "unsupportedConfiguration");
        EndpointDescription endpoint = new EndpointDescription(p);
        IntentMap intentMap = new IntentMap(new DefaultIntentMapFactory().create());
        IntentManager intentManager = new IntentManagerImpl(intentMap, 10000);
        HttpServiceManager httpServiceManager = c.createMock(HttpServiceManager.class);
        CXFDistributionProvider provider = new CXFDistributionProvider(bc, intentManager, httpServiceManager);
        c.replay();

        RemoteServiceAdminCore rsaCore = new RemoteServiceAdminCore(bc, provider) {
            @Override
            protected ImportRegistrationImpl exposeServiceFactory(String interfaceName, 
                                                                      EndpointDescription epd,
                                                                      DistributionProvider handler) {
                return new ImportRegistrationImpl(epd, this);
            }
        };

        // must be null as the endpoint doesn't contain any usable configurations
        assertNull(rsaCore.importService(endpoint));
        // must be empty
        assertEquals(0, rsaCore.getImportedEndpoints().size());

        p.put(RemoteConstants.SERVICE_IMPORTED_CONFIGS, org.apache.cxf.dosgi.dsw.Constants.WS_CONFIG_TYPE);
        endpoint = new EndpointDescription(p);

        ImportRegistration ireg = rsaCore.importService(endpoint);
        assertNotNull(ireg);

        assertEquals(1, rsaCore.getImportedEndpoints().size());

        // lets import the same endpoint once more -> should get a copy of the ImportRegistration
        ImportRegistration ireg2 = rsaCore.importService(endpoint);
        assertNotNull(ireg2);
        assertEquals(2, rsaCore.getImportedEndpoints().size());

        assertEquals(ireg.getImportReference(), (rsaCore.getImportedEndpoints().toArray())[0]);

        assertEquals(ireg.getImportReference().getImportedEndpoint(), ireg2.getImportReference()
            .getImportedEndpoint());

        // remove the registration

        // first call shouldn't remove the import
        ireg2.close();
        assertEquals(1, rsaCore.getImportedEndpoints().size());

        // second call should really close and remove the import
        ireg.close();
        assertEquals(0, rsaCore.getImportedEndpoints().size());

        c.verify();
    }

    @Test
    public void testExport() throws Exception {
        BundleContext bc = EasyMock.createMock(BundleContext.class);
        EasyMock.expect(bc.getProperty(Constants.FRAMEWORK_VERSION)).andReturn(null).anyTimes();
        bc.addServiceListener(EasyMock.<ServiceListener>anyObject(), EasyMock.<String>anyObject());
        EasyMock.expectLastCall().anyTimes();
        bc.removeServiceListener(EasyMock.<ServiceListener>anyObject());
        EasyMock.expectLastCall().anyTimes();
        EasyMock.expect(bc.getServiceReferences(EasyMock.<String>anyObject(),
                                                EasyMock.<String>anyObject())).andReturn(null).anyTimes();
        EasyMock.expect(bc.getAllServiceReferences(EasyMock.<String>anyObject(),
                                                   EasyMock.<String>anyObject())).andReturn(null).anyTimes();

        Bundle b = createDummyRsaBundle(bc);

        final Map<String, Object> sProps = new HashMap<String, Object>();
        sProps.put("objectClass", new String[] {"java.lang.Runnable"});
        sProps.put("service.id", 51L);
        sProps.put("myProp", "myVal");
        sProps.put("service.exported.interfaces", "*");
        ServiceReference sref = mockServiceReference(sProps);

        Runnable svcObject = EasyMock.createNiceMock(Runnable.class);
        EasyMock.replay(svcObject);

        EasyMock.expect(bc.getService(sref)).andReturn(svcObject).anyTimes();
        EasyMock.expect(bc.getBundle()).andReturn(b).anyTimes();
        EasyMock.expect(bc.createFilter("(service.id=51)"))
            .andReturn(FrameworkUtil.createFilter("(service.id=51)")).anyTimes();
        EasyMock.replay(bc);

        Map<String, Object> eProps = new HashMap<String, Object>(sProps);
        eProps.put("endpoint.id", "http://something");
        eProps.put("service.imported.configs", new String[] {"org.apache.cxf.ws"});
        Endpoint er = new ServerWrapper(new EndpointDescription(eProps), null);

        DistributionProvider handler = EasyMock.createNiceMock(DistributionProvider.class);
        EasyMock.expect(handler.exportService(sref, sProps, Runnable.class.getName())).andReturn(er).once();
        EasyMock.replay(handler);

        RemoteServiceAdminCore rsaCore = new RemoteServiceAdminCore(bc, handler);

        // Export the service for the first time
        List<ExportRegistration> ereg = rsaCore.exportService(sref, null);
        assertEquals(1, ereg.size());
        assertNull(ereg.get(0).getException());
        assertSame(sref, ereg.get(0).getExportReference().getExportedService());
        EndpointDescription endpoint = ereg.get(0).getExportReference().getExportedEndpoint();

        Map<String, Object> edProps = endpoint.getProperties();
        assertEquals("http://something", edProps.get("endpoint.id"));
        assertNotNull(edProps.get("service.imported"));
        assertTrue(Arrays.equals(new String[] {"java.lang.Runnable"},
                                 (Object[]) edProps.get("objectClass")));
        assertTrue(Arrays.equals(new String[] {"org.apache.cxf.ws"},
                                 (Object[]) edProps.get("service.imported.configs")));

        // Ask to export the same service again, this should not go through the whole process again but simply return
        // a copy of the first instance.
        final Map<String, Object> sProps2 = new HashMap<String, Object>();
        sProps2.put("objectClass", new String[] {"java.lang.Runnable"});
        sProps2.put("service.id", 51L);
        sProps2.put("service.exported.interfaces", "*");
        ServiceReference sref2 = mockServiceReference(sProps2);
        Map<String, Object> props2 = new HashMap<String, Object>();
        props2.put("myProp", "myVal");
        List<ExportRegistration> ereg2 = rsaCore.exportService(sref2, props2);

        assertEquals(1, ereg2.size());
        assertNull(ereg2.get(0).getException());
        assertEquals(ereg.get(0).getExportReference().getExportedEndpoint().getProperties(),
                ereg2.get(0).getExportReference().getExportedEndpoint().getProperties());

        // Look at the exportedServices data structure
        Field field = RemoteServiceAdminCore.class.getDeclaredField("exportedServices");
        field.setAccessible(true);
        Map<Map<String, Object>, Collection<ExportRegistration>> exportedServices =
                (Map<Map<String, Object>, Collection<ExportRegistration>>) field.get(rsaCore);

        assertEquals("One service was exported", 1, exportedServices.size());
        assertEquals("There are 2 export registrations (identical copies)",
                2, exportedServices.values().iterator().next().size());

        // Unregister one of the exports
        rsaCore.removeExportRegistration((ExportRegistrationImpl) ereg.get(0));
        assertEquals("One service was exported", 1, exportedServices.size());
        assertEquals("There 1 export registrations left",
                1, exportedServices.values().iterator().next().size());

        // Unregister the other export
        rsaCore.removeExportRegistration((ExportRegistrationImpl) ereg2.get(0));
        assertEquals("No more exported services", 0, exportedServices.size());
    }

    private Bundle createDummyRsaBundle(BundleContext bc) {
        Bundle b = EasyMock.createNiceMock(Bundle.class);
        EasyMock.expect(b.getBundleContext()).andReturn(bc).anyTimes();
        EasyMock.expect(b.getSymbolicName()).andReturn("rsabundle").anyTimes();
        EasyMock.expect(b.getHeaders()).andReturn(new Hashtable<String, String>()).anyTimes();
        EasyMock.replay(b);
        return b;
    }

    @Test
    public void testExportException() throws Exception {
        BundleContext bc = EasyMock.createNiceMock(BundleContext.class);

        Bundle b = createDummyRsaBundle(bc);

        final Map<String, Object> sProps = new HashMap<String, Object>();
        sProps.put("objectClass", new String[] {"java.lang.Runnable"});
        sProps.put("service.id", 51L);
        sProps.put("service.exported.interfaces", "*");
        ServiceReference sref = mockServiceReference(sProps);

        Runnable svcObject = EasyMock.createNiceMock(Runnable.class);
        EasyMock.replay(svcObject);

        EasyMock.expect(bc.getService(sref)).andReturn(svcObject).anyTimes();
        EasyMock.expect(bc.getBundle()).andReturn(b).anyTimes();
        EasyMock.replay(bc);

        Map<String, Object> eProps = new HashMap<String, Object>(sProps);
        eProps.put("endpoint.id", "http://something");
        eProps.put("service.imported.configs", new String[] {"org.apache.cxf.ws"});

        DistributionProvider handler = EasyMock.createMock(DistributionProvider.class);
        EasyMock.expect(handler.exportService(sref, sProps, Runnable.class.getName())).andThrow(new TestException());
        EasyMock.replay(handler);

        RemoteServiceAdminCore rsaCore = new RemoteServiceAdminCore(bc, handler);

        List<ExportRegistration> ereg = rsaCore.exportService(sref, sProps);
        assertEquals(1, ereg.size());
        assertTrue(ereg.get(0).getException() instanceof TestException);

        // Look at the exportedServices data structure
        Field field = RemoteServiceAdminCore.class.getDeclaredField("exportedServices");
        field.setAccessible(true);
        Map<Map<String, Object>, Collection<ExportRegistration>> exportedServices =
                (Map<Map<String, Object>, Collection<ExportRegistration>>) field.get(rsaCore);

        assertEquals("One service was exported", 1, exportedServices.size());
        assertEquals("There is 1 export registration",
                1, exportedServices.values().iterator().next().size());

    }

    private ServiceReference mockServiceReference(final Map<String, Object> sProps) {
        BundleContext bc = EasyMock.createNiceMock(BundleContext.class);

        Bundle b = EasyMock.createNiceMock(Bundle.class);
        EasyMock.expect(b.getBundleContext()).andReturn(bc).anyTimes();
        EasyMock.replay(b);

        EasyMock.expect(bc.getBundle()).andReturn(b).anyTimes();
        EasyMock.replay(bc);

        ServiceReference sref = EasyMock.createNiceMock(ServiceReference.class);
        EasyMock.expect(sref.getBundle()).andReturn(b).anyTimes();
        EasyMock.expect(sref.getPropertyKeys()).andReturn(sProps.keySet().toArray(new String[] {})).anyTimes();
        EasyMock.expect(sref.getProperty((String) EasyMock.anyObject())).andAnswer(new IAnswer<Object>() {
            @Override
            public Object answer() throws Throwable {
                return sProps.get(EasyMock.getCurrentArguments()[0]);
            }
        }).anyTimes();
        EasyMock.replay(sref);
        return sref;
    }

    @SuppressWarnings("serial")
    private static class TestException extends RuntimeException {
    }
    
    public void testOverlayProperties() {
        Map<String, Object> sProps = new HashMap<String, Object>();
        Map<String, Object> aProps = new HashMap<String, Object>();

        RemoteServiceAdminCore.overlayProperties(sProps, aProps);
        assertEquals(0, sProps.size());

        sProps.put("aaa", "aval");
        sProps.put("bbb", "bval");
        sProps.put(Constants.OBJECTCLASS, new String[] {"X"});
        sProps.put(Constants.SERVICE_ID, 17L);

        aProps.put("AAA", "achanged");
        aProps.put("CCC", "CVAL");
        aProps.put(Constants.OBJECTCLASS, new String[] {"Y"});
        aProps.put(Constants.SERVICE_ID.toUpperCase(), 51L);

        Map<String, Object> aPropsOrg = new HashMap<String, Object>(aProps);
        RemoteServiceAdminCore.overlayProperties(sProps, aProps);
        assertEquals("The additional properties should not be modified", aPropsOrg, aProps);

        assertEquals(5, sProps.size());
        assertEquals("achanged", sProps.get("aaa"));
        assertEquals("bval", sProps.get("bbb"));
        assertEquals("CVAL", sProps.get("CCC"));
        assertTrue("Should not be possible to override the objectClass property",
                Arrays.equals(new String[] {"X"}, (Object[]) sProps.get(Constants.OBJECTCLASS)));
        assertEquals("Should not be possible to override the service.id property",
                17L, sProps.get(Constants.SERVICE_ID));
    }
}
