/*
 * 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.sling.testing.mock.osgi;

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;

import com.google.common.collect.ImmutableMap;

public class OsgiServiceUtilTest {

    private BundleContext bundleContext = MockOsgi.newBundleContext();
    private Service1 service1;
    private Service2 service2;

    @Before
    public void setUp() {
        service1 = new Service1();
        service2 = new Service2();
        bundleContext.registerService(ServiceInterface1.class.getName(), service1, null);
        bundleContext.registerService(ServiceInterface2.class.getName(), service2, null);
        bundleContext.registerService(ServiceInterface3.class.getName(), service2, null);
    }
    
    @After
    public void tearDown() {
        MockOsgi.shutdown(bundleContext);
    }

    @Test
    public void testService3() {
        Service3 service3 = new Service3();
        assertTrue(MockOsgi.injectServices(service3, bundleContext));

        Dictionary<String, Object> service3Config = new Hashtable<String, Object>();
        service3Config.put("prop1", "value1");
        assertTrue(MockOsgi.activate(service3, bundleContext, service3Config));

        assertNotNull(service3.getComponentContext());
        assertEquals(service3Config.get("prop1"), service3.getComponentContext().getProperties().get("prop1"));

        assertSame(service1, service3.getReference1());

        List<ServiceInterface2> references2 = service3.getReferences2();
        assertEquals(1, references2.size());
        assertSame(service2, references2.get(0));

        List<ServiceSuperInterface3> references3 = service3.getReferences3();
        assertEquals(1, references3.size());
        assertSame(service2, references3.get(0));

        List<Map<String, Object>> reference3Configs = service3.getReference3Configs();
        assertEquals(1, reference3Configs.size());
        assertEquals(200, reference3Configs.get(0).get(Constants.SERVICE_RANKING));

        Set<ServiceSuperInterface3> references3Set = service3.getReferences3Set();
        assertEquals(1, references3Set.size());
        assertSame(service2, references3Set.iterator().next());

        assertTrue(MockOsgi.deactivate(service3, bundleContext));
        assertNull(service3.getComponentContext());
    }

    @Test
    public void testService3OsgiR6() {
        Service3OsgiR6 service3 = new Service3OsgiR6();
        assertTrue(MockOsgi.injectServices(service3, bundleContext));

        Dictionary<String, Object> service3Config = new Hashtable<String, Object>();
        service3Config.put("prop1", "value1");
        assertTrue(MockOsgi.activate(service3, bundleContext, service3Config));

        assertNotNull(service3.getComponentContext());
        assertEquals(service3Config.get("prop1"), service3.getComponentContext().getProperties().get("prop1"));

        assertSame(service1, service3.getReference1());

        List<ServiceInterface2> references2 = service3.getReferences2();
        assertEquals(1, references2.size());
        assertSame(service2, references2.get(0));

        List<ServiceSuperInterface3> references3 = service3.getReferences3();
        assertEquals(1, references3.size());
        assertSame(service2, references3.get(0));

        Set<ServiceSuperInterface3> references3Set = service3.getReferences3Set();
        assertEquals(1, references3Set.size());
        assertSame(service2, references3Set.iterator().next());

        Collection<ServiceSuperInterface3> references3Collection = service3.getReferences3Collection();
        assertEquals(1, references3Collection.size());
        assertSame(service2, references3Collection.iterator().next());

        assertTrue(MockOsgi.deactivate(service3, bundleContext));
        assertNull(service3.getComponentContext());
    }

    @Test
    public void testService3_Config() {
        BundleContext bundleContext = MockOsgi.newBundleContext();

        Map<String,Object> initialProperites = ImmutableMap.<String, Object>of("prop1", "value1");

        Service3 service3 = new Service3();
        MockOsgi.activate(service3, bundleContext, initialProperites);
        assertEquals(initialProperites.get("prop1"), service3.getConfig().get("prop1"));

        Map<String,Object> newProperties = ImmutableMap.<String, Object>of("prop2", "value2");
        MockOsgi.modified(service3, bundleContext, newProperties);
        assertEquals(newProperties.get("prop2"), service3.getConfig().get("prop2"));

        newProperties = ImmutableMap.<String, Object>of("prop3", "value3");
        Dictionary<String,Object> newPropertiesDictonary = new Hashtable<String,Object>(newProperties);
        MockOsgi.modified(service3, bundleContext, newPropertiesDictonary);
        assertEquals(newProperties.get("prop3"), service3.getConfig().get("prop3"));

        MockOsgi.modified(service3, bundleContext, "prop3", "value4");
        assertEquals("value4", service3.getConfig().get("prop3"));
    }

    @Test
    public void testService4() {
        Service4 service4 = new Service4();

        assertTrue(MockOsgi.injectServices(service4, bundleContext));
        assertFalse(MockOsgi.activate(service4, bundleContext));

        assertSame(service1, service4.getReference1());
    }

    @Test(expected=NoScrMetadataException.class)
    public void testInjectServicesNoMetadata() {
        MockOsgi.injectServices(new Object(), MockOsgi.newBundleContext());
    }

    @Test(expected=NoScrMetadataException.class)
    public void testActivateNoMetadata() {
        MockOsgi.activate(new Object(), bundleContext);
    }

    @Test(expected=NoScrMetadataException.class)
    public void testDeactivateNoMetadata() {
        MockOsgi.deactivate(new Object(), bundleContext);
    }

    @Test(expected=NoScrMetadataException.class)
    public void testModifiedNoMetadata() {
        MockOsgi.modified(new Object(), MockOsgi.newBundleContext(), ImmutableMap.<String,Object>of());
    }

    @Test
    public void testMockedService() {
        Service5 service5 = Mockito.spy(new Service5());
        Mockito.doReturn(true).when(service5).doRemoteThing();

        MockOsgi.injectServices(service5, bundleContext);
        MockOsgi.activate(service5, bundleContext, (Dictionary<String, Object>) null);
        bundleContext.registerService(ServiceInterface5.class.getName(), service5, null);

        assertSame(service5, bundleContext.getService(
                bundleContext.getServiceReference(ServiceInterface5.class.getName())));
        assertEquals(true, service5.doRemoteThing());
    }

    @Test
    public void testServiceFactoryViaScr() {
        ServiceFactory1 serviceFactory1 = new ServiceFactory1();
        
        MockOsgi.injectServices(serviceFactory1, bundleContext);
        MockOsgi.activate(serviceFactory1, bundleContext, (Dictionary<String, Object>) null);
        bundleContext.registerService(ServiceFactory1.class.getName(), serviceFactory1, null);

        assertSame(serviceFactory1, bundleContext.getService(
                bundleContext.getServiceReference(ServiceFactory1.class.getName())));
    }

    @Test
    public void testServiceFactoryViaManualRegistration() {
        final ServiceFactory1 serviceFactory1 = new ServiceFactory1();
        
        bundleContext.registerService(ServiceFactory1.class.getName(), new ServiceFactory() {
            @Override
            public Object getService(Bundle bundle, ServiceRegistration registration) {
                return serviceFactory1;
            }
            @Override
            public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
                // nothing to do
            }
        }, null);

        assertSame(serviceFactory1, bundleContext.getService(
                bundleContext.getServiceReference(ServiceFactory1.class.getName())));
    }

    
    public interface ServiceInterface1 {
        // no methods
    }

    public interface ServiceInterface1Optional {
        // no methods
    }

    public interface ServiceInterface2 {
        // no methods
    }

    public interface ServiceInterface3 extends ServiceSuperInterface3 {
        // no methods
    }

    public interface ServiceSuperInterface3 {
        // no methods
    }

    @Component(service = ServiceInterface1.class,
            property = Constants.SERVICE_RANKING + ":Integer=100")
    public static class Service1 implements ServiceInterface1 {
        // dummy interface
    }

    @Component(service = { ServiceInterface2.class, ServiceInterface3.class },
            property = Constants.SERVICE_RANKING + ":Integer=200")
    public static class Service2 implements ServiceInterface2, ServiceInterface3 {
        // dummy interface
    }

    @Component(reference = { @Reference(name = "reference2", service = ServiceInterface2.class, cardinality = ReferenceCardinality.AT_LEAST_ONE,
            bind="bindReference2", unbind="unbindReference2") })
    public static class Service3 {

        @Reference(bind="bindReference1", unbind="unbindReference1")
        private ServiceInterface1 reference1;
        @Reference(cardinality = ReferenceCardinality.OPTIONAL, bind="bindReference1Optional", unbind="unbindReference1Optional")
        private ServiceInterface1Optional reference1Optional;

        private List<ServiceReference> references2 = new ArrayList<>();

        @Reference(name = "reference3", service = ServiceInterface3.class, cardinality = ReferenceCardinality.MULTIPLE,
                bind="bindReference3", unbind="unbindReference3")
        private List<ServiceSuperInterface3> references3 = new ArrayList<>();
        private List<Map<String, Object>> reference3Configs = new ArrayList<>();

        @Reference(name = "references3Set", service = ServiceInterface3.class, cardinality = ReferenceCardinality.MULTIPLE,
                bind="bindReferenceSet3", unbind="unbindReferenceSet3")
        private Set<ServiceSuperInterface3> references3Set = new HashSet<>();

        private ComponentContext componentContext;
        private Map<String, Object> config;

        @Activate
        private void activate(ComponentContext ctx) {
            this.componentContext = ctx;
            this.config = MapUtil.toMap(ctx.getProperties());
        }

        @Deactivate
        private void deactivate(ComponentContext ctx) {
            this.componentContext = null;
        }

        @Modified
        private void modified(Map<String,Object> newConfig) {
            this.config = newConfig;
        }

        public ServiceInterface1 getReference1() {
            return this.reference1;
        }

        public ServiceInterface1Optional getReference1Optional() {
            return this.reference1Optional;
        }

        public List<ServiceInterface2> getReferences2() {
            List<ServiceInterface2> services = new ArrayList<>();
            for (ServiceReference<?> serviceReference : references2) {
                services.add((ServiceInterface2)componentContext.getBundleContext().getService(serviceReference));
            }
            return services;
        }

        public List<ServiceSuperInterface3> getReferences3() {
            return this.references3;
        }

        public List<Map<String, Object>> getReference3Configs() {
            return this.reference3Configs;
        }

        public Set<ServiceSuperInterface3> getReferences3Set() {
            return this.references3Set;
        }

        public ComponentContext getComponentContext() {
            return this.componentContext;
        }

        public Map<String, Object> getConfig() {
            return config;
        }

        protected void bindReference1Optional(ServiceInterface1Optional service) {
            reference1Optional = service;
        }

        protected void unbindReference1Optional(ServiceInterface1Optional service) {
            reference1Optional = null;
        }

        protected void bindReference1(ServiceInterface1 service) {
            reference1 = service;
        }

        protected void unbindReference1(ServiceInterface1 service) {
            reference1 = null;
        }

        protected void bindReference2(ServiceReference serviceReference) {
            references2.add(serviceReference);
        }

        protected void unbindReference2(ServiceReference serviceReference) {
            references2.remove(serviceReference);
        }

        protected void bindReference3(ServiceSuperInterface3 service, Map<String, Object> serviceConfig) {
            references3.add(service);
            reference3Configs.add(serviceConfig);
        }

        protected void unbindReference3(ServiceSuperInterface3 service, Map<String, Object> serviceConfig) {
            references3.remove(service);
            reference3Configs.remove(serviceConfig);
        }

        protected void bindReference3Set(ServiceSuperInterface3 service, Map<String, Object> serviceConfig) {
            references3Set.add(service);
        }

        protected void unbindReference3Set(ServiceSuperInterface3 service, Map<String, Object> serviceConfig) {
            references3Set.remove(service);
        }

    }

    public static class Service3OsgiR6 {

        private ServiceInterface1 reference1;
        private ServiceInterface1Optional reference1Optional;
        private List<ServiceReference> references2;
        private List<ServiceSuperInterface3> references3;
        private List<ServiceSuperInterface3> references3Filtered;
        private ServiceSuperInterface3 reference3DynamicFiltered;
        private Set<ServiceSuperInterface3> references3Set;
        private Collection<ServiceSuperInterface3> references3Collection;

        private ComponentContext componentContext;
        private Map<String, Object> config;

        @Activate
        private void activate(ComponentContext ctx) {
            this.componentContext = ctx;
            this.config = MapUtil.toMap(ctx.getProperties());
        }

        @Deactivate
        private void deactivate(ComponentContext ctx) {
            this.componentContext = null;
        }

        @Modified
        private void modified(Map<String,Object> newConfig) {
            this.config = newConfig;
        }

        public ServiceInterface1 getReference1() {
            return this.reference1;
        }

        public ServiceInterface1Optional getReference1Optional() {
            return this.reference1Optional;
        }

        public List<ServiceInterface2> getReferences2() {
            List<ServiceInterface2> services = new ArrayList<ServiceInterface2>();
            for (ServiceReference<?> serviceReference : references2) {
                services.add((ServiceInterface2)componentContext.getBundleContext().getService(serviceReference));
            }
            return services;
        }

        public List<ServiceSuperInterface3> getReferences3() {
            return this.references3;
        }

        public List<ServiceSuperInterface3> getReferences3Filtered() {
            return this.references3Filtered;
        }


        public ServiceSuperInterface3 getReference3DynamicFiltered() {
            return this.reference3DynamicFiltered;
        }

        public Set<ServiceSuperInterface3> getReferences3Set() {
            return this.references3Set;
        }

        public Collection<ServiceSuperInterface3> getReferences3Collection() {
            return this.references3Collection;
        }

        public ComponentContext getComponentContext() {
            return this.componentContext;
        }

        public Map<String, Object> getConfig() {
            return config;
        }

    }

    public interface Service3StaticGreedy {
        ServiceInterface1 getReference1();
        ServiceInterface1Optional getReference1Optional();
        List<ServiceInterface2> getReferences2();
        List<ServiceSuperInterface3> getReferences3();
        List<Map<String, Object>> getReference3Configs();
    }

    @Component(service= Service3StaticGreedy.class,
            reference = { @Reference(name = "reference2", service = ServiceInterface2.class, cardinality = ReferenceCardinality.AT_LEAST_ONE,
            bind="bindReference2", unbind="unbindReference2") })
    public static class Service3StaticGreedyImpl implements Service3StaticGreedy {

        @Reference(bind="bindReference1", unbind="unbindReference1")
        private ServiceInterface1 reference1;
        @Reference(cardinality = ReferenceCardinality.OPTIONAL, bind="bindReference1Optional", unbind="unbindReference1Optional")
        private ServiceInterface1Optional reference1Optional;

        private List<ServiceReference> references2 = new ArrayList<ServiceReference>();

        @Reference(name = "reference3", service = ServiceInterface3.class, cardinality = ReferenceCardinality.MULTIPLE,
                bind="bindReference3", unbind="unbindReference3")
        private List<ServiceSuperInterface3> references3 = new ArrayList<ServiceSuperInterface3>();
        private List<Map<String, Object>> reference3Configs = new ArrayList<Map<String, Object>>();

        private ComponentContext componentContext;
        private Map<String, Object> config;

        @Activate
        private void activate(ComponentContext ctx) {
            this.componentContext = ctx;
            this.config = MapUtil.toMap(ctx.getProperties());
        }

        @Deactivate
        private void deactivate(ComponentContext ctx) {
            this.componentContext = null;
        }

        @Modified
        private void modified(Map<String,Object> newConfig) {
            this.config = newConfig;
        }

        @Override
        public ServiceInterface1 getReference1() {
            return this.reference1;
        }

        @Override
        public ServiceInterface1Optional getReference1Optional() {
            return this.reference1Optional;
        }

        @Override
        public List<ServiceInterface2> getReferences2() {
            List<ServiceInterface2> services = new ArrayList<ServiceInterface2>();
            for (ServiceReference<?> serviceReference : references2) {
                services.add((ServiceInterface2)componentContext.getBundleContext().getService(serviceReference));
            }
            return services;
        }

        @Override
        public List<ServiceSuperInterface3> getReferences3() {
            return this.references3;
        }

        @Override
        public List<Map<String, Object>> getReference3Configs() {
            return this.reference3Configs;
        }

        public ComponentContext getComponentContext() {
            return this.componentContext;
        }

        public Map<String, Object> getConfig() {
            return config;
        }

        protected void bindReference1Optional(ServiceInterface1Optional service) {
            reference1Optional = service;
        }

        protected void unbindReference1Optional(ServiceInterface1Optional service) {
            reference1Optional = null;
        }

        protected void bindReference1(ServiceInterface1 service) {
            reference1 = service;
        }

        protected void unbindReference1(ServiceInterface1 service) {
            reference1 = null;
        }

        protected void bindReference2(ServiceReference serviceReference) {
            references2.add(serviceReference);
        }

        protected void unbindReference2(ServiceReference serviceReference) {
            references2.remove(serviceReference);
        }

        protected void bindReference3(ServiceSuperInterface3 service, Map<String, Object> serviceConfig) {
            references3.add(service);
            reference3Configs.add(serviceConfig);
        }

        protected void unbindReference3(ServiceSuperInterface3 service, Map<String, Object> serviceConfig) {
            references3.remove(service);
            reference3Configs.remove(serviceConfig);
        }

    }

    @Component(reference = @Reference(service = ServiceInterface1.class, name = "customName", bind = "customBind", unbind = "customUnbind"))
    public static class Service4 {

        private ServiceInterface1 reference1;

        public ServiceInterface1 getReference1() {
            return this.reference1;
        }

        protected void customBind(ServiceInterface1 service) {
            reference1 = service;
        }

        protected void customUnbind(ServiceInterface1 service) {
            reference1 = null;
        }

    }

    @Component(service = { ServiceInterface5.class })
    public static class Service5 implements ServiceInterface5 {

        @Override
        public boolean doRemoteThing() {
            return false;
        }
    }

    public interface ServiceInterface5 {

        boolean doRemoteThing();

    }

    @Component(service = ServiceFactory1.class, servicefactory = true)
    public static class ServiceFactory1 {
        
    }
        
}
