/**
 * 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.handlers.ws;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.xml.namespace.QName;

import org.apache.aries.rsa.spi.Endpoint;
import org.apache.aries.rsa.util.EndpointHelper;
import org.apache.cxf.dosgi.common.endpoint.ServerEndpoint;
import org.apache.cxf.dosgi.common.httpservice.HttpServiceManager;
import org.apache.cxf.dosgi.common.intent.IntentManager;
import org.apache.cxf.dosgi.common.intent.impl.IntentManagerImpl;
import org.apache.cxf.dosgi.dsw.handlers.jaxws.MyJaxWsEchoService;
import org.apache.cxf.dosgi.dsw.handlers.simple.MySimpleEchoService;
import org.apache.cxf.endpoint.EndpointImpl;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.frontend.ClientFactoryBean;
import org.apache.cxf.frontend.ClientProxyFactoryBean;
import org.apache.cxf.frontend.ServerFactoryBean;
import org.apache.cxf.jaxws.support.JaxWsEndpointImpl;
import org.apache.cxf.transport.Destination;
import org.apache.cxf.ws.addressing.AttributedURIType;
import org.apache.cxf.ws.addressing.EndpointReferenceType;
import org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.easymock.IMocksControl;
import org.junit.Assert;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import org.osgi.service.remoteserviceadmin.EndpointDescription;
import org.osgi.service.remoteserviceadmin.RemoteConstants;

import junit.framework.TestCase;

public class PojoConfigurationTypeHandlerTest extends TestCase {

    public void testGetPojoAddressEndpointURI() {
        IntentManager intentManager = new IntentManagerImpl();
        WsProvider handler = new WsProvider();
        handler.setIntentManager(intentManager);
        handler.setHttpServiceManager(dummyHttpServiceManager());
        Map<String, Object> sd = new HashMap<String, Object>();
        String url = "http://somewhere:1234/blah";
        sd.put(RemoteConstants.ENDPOINT_ID, url);
        assertEquals(url, handler.getServerAddress(sd, String.class));
    }

    private HttpServiceManager dummyHttpServiceManager() {
        return new HttpServiceManager();
    }

    public void testGetPojoAddressEndpointCxf() {
        IntentManager intentManager = new IntentManagerImpl();
        WsProvider handler = new WsProvider();
        handler.setIntentManager(intentManager);
        handler.setHttpServiceManager(dummyHttpServiceManager());
        Map<String, Object> sd = new HashMap<String, Object>();
        String url = "http://somewhere:29/boo";
        sd.put("org.apache.cxf.ws.address", url);
        assertEquals(url, handler.getServerAddress(sd, String.class));
    }

    public void testGetDefaultPojoAddress() {
        IntentManager intentManager = new IntentManagerImpl();
        WsProvider handler = new WsProvider();
        handler.setIntentManager(intentManager);
        handler.setHttpServiceManager(dummyHttpServiceManager());
        Map<String, Object> sd = new HashMap<String, Object>();
        assertEquals("/java/lang/String", handler.getServerAddress(sd, String.class));
    }

    // todo: add test for data bindings
    public void testCreateProxy() {
        IMocksControl c = EasyMock.createNiceControl();
        BundleContext bc1 = c.createMock(BundleContext.class);

        BundleContext requestingContext = c.createMock(BundleContext.class);

        final ClientProxyFactoryBean cpfb = c.createMock(ClientProxyFactoryBean.class);
        ReflectionServiceFactoryBean sf = c.createMock(ReflectionServiceFactoryBean.class);
        EasyMock.expect(cpfb.getServiceFactory()).andReturn(sf).anyTimes();
        ClientFactoryBean cf = c.createMock(ClientFactoryBean.class);
        EasyMock.expect(cpfb.getClientFactoryBean()).andReturn(cf).anyTimes();
        IntentManager intentManager = new IntentManagerImpl();
        WsProvider p = new WsProvider() {
            @Override
            protected ClientProxyFactoryBean createClientProxyFactoryBean(Map<String, Object> sd,
                                                                          Class<?> iClass) {
                return cpfb;
            }
        };
        p.setIntentManager(intentManager);
        p.setHttpServiceManager(dummyHttpServiceManager());
        p.activate(bc1);

        Class<?>[] exportedInterfaces = new Class[] {Runnable.class};

        Map<String, Object> props = new HashMap<String, Object>();
        props.put(RemoteConstants.ENDPOINT_ID, "http://google.de/");
        EndpointHelper.addObjectClass(props, exportedInterfaces);
        props.put(RemoteConstants.SERVICE_IMPORTED_CONFIGS, new String[] {"my.config"});
        EndpointDescription endpoint = new EndpointDescription(props);

        cpfb.setAddress((String)EasyMock.eq(props.get(RemoteConstants.ENDPOINT_ID)));
        EasyMock.expectLastCall().atLeastOnce();

        cpfb.setServiceClass(EasyMock.eq(Runnable.class));
        EasyMock.expectLastCall().atLeastOnce();

        c.replay();
        ClassLoader cl = null;
        Object proxy = p.importEndpoint(cl, requestingContext, exportedInterfaces, endpoint);
        assertNotNull(proxy);
        assertTrue("Proxy is not of the requested type! ", proxy instanceof Runnable);
        c.verify();
    }

    public void testCreateServerWithAddressProperty() throws Exception {
        BundleContext dswContext = EasyMock.createNiceMock(BundleContext.class);
        EasyMock.replay(dswContext);

        String myService = "Hi";
        final ServerFactoryBean sfb = createMockServerFactoryBean();

        IntentManager intentManager = new IntentManagerImpl();
        WsProvider p = new WsProvider() {
            @Override
            protected ServerFactoryBean createServerFactoryBean(Map<String, Object> sd, Class<?> iClass) {
                return sfb;
            }
        };
        p.activate(dswContext);
        p.setIntentManager(intentManager);
        p.setHttpServiceManager(dummyHttpServiceManager());
        BundleContext bundleContext = EasyMock.createNiceMock(BundleContext.class);
        EasyMock.replay(bundleContext);

        Class<?>[] exportedInterface = new Class[] {String.class
        };
        Map<String, Object> props = new HashMap<String, Object>();
        EndpointHelper.addObjectClass(props, exportedInterface);
        props.put(WsConstants.WS_ADDRESS_PROPERTY, "http://alternate_host:80/myString");

        Endpoint exportResult = p.exportService(myService, bundleContext, props, exportedInterface);
        Map<String, Object> edProps = exportResult.description().getProperties();

        assertNotNull(edProps.get(RemoteConstants.SERVICE_IMPORTED_CONFIGS));
        assertEquals(1, ((String[])edProps.get(RemoteConstants.SERVICE_IMPORTED_CONFIGS)).length);
        assertEquals(WsConstants.WS_CONFIG_TYPE,
                     ((String[])edProps.get(RemoteConstants.SERVICE_IMPORTED_CONFIGS))[0]);
        assertEquals("http://alternate_host:80/myString", edProps.get(RemoteConstants.ENDPOINT_ID));
    }

    public void testAddressing() throws Exception {
        runAddressingTest(new HashMap<String, Object>(), "http://localhost:9000/java/lang/Runnable");

        Map<String, Object> p1 = new HashMap<String, Object>();
        p1.put("org.apache.cxf.ws.address", "http://somewhere");
        runAddressingTest(p1, "http://somewhere");

        Map<String, Object> p3 = new HashMap<String, Object>();
        p3.put("org.apache.cxf.ws.port", 65535);
        runAddressingTest(p3, "http://localhost:65535/java/lang/Runnable");

        Map<String, Object> p4 = new HashMap<String, Object>();
        p4.put("org.apache.cxf.ws.port", "8181");
        runAddressingTest(p4, "http://localhost:8181/java/lang/Runnable");
    }

    private void runAddressingTest(Map<String, Object> properties, String expectedAddress) throws Exception {
        Class<?>[] exportedInterface = new Class[] {Runnable.class};
        EndpointHelper.addObjectClass(properties, exportedInterface);
        BundleContext dswContext = EasyMock.createNiceMock(BundleContext.class);
        String expectedUUID = UUID.randomUUID().toString();
        EasyMock.expect(dswContext.getProperty(org.osgi.framework.Constants.FRAMEWORK_UUID))
            .andReturn(expectedUUID);
        EasyMock.replay(dswContext);

        IntentManager intentManager = EasyMock.createNiceMock(IntentManager.class);
        EasyMock.replay(intentManager);

        WsProvider handler = new WsProvider() {
            @Override
            protected Endpoint createServerFromFactory(ServerFactoryBean factory, EndpointDescription epd) {
                return new ServerEndpoint(epd, null);
            }
        };
        handler.setIntentManager(intentManager);
        handler.setHttpServiceManager(dummyHttpServiceManager());
        handler.activate(dswContext);
        Runnable myService = EasyMock.createMock(Runnable.class);
        EasyMock.replay(myService);

        BundleContext bundleContext = EasyMock.createNiceMock(BundleContext.class);
        EasyMock.replay(bundleContext);

        Endpoint result = handler.exportService(myService, bundleContext, properties, exportedInterface);
        Map<String, Object> props = result.description().getProperties();
        assertEquals(expectedAddress, props.get("org.apache.cxf.ws.address"));
        Assert.assertArrayEquals(new String[] {"org.apache.cxf.ws"}, 
                                 (String[])props.get(RemoteConstants.SERVICE_IMPORTED_CONFIGS));
        Assert.assertArrayEquals(new String[] {"java.lang.Runnable"}, 
                                 (String[])props.get(org.osgi.framework.Constants.OBJECTCLASS));
    }

    public void t2estCreateServerException() {
        BundleContext dswContext = EasyMock.createNiceMock(BundleContext.class);
        EasyMock.replay(dswContext);

        IntentManager intentManager = EasyMock.createNiceMock(IntentManager.class);
        EasyMock.replay(intentManager);

        WsProvider handler = new WsProvider() {
            @Override
            protected Endpoint createServerFromFactory(ServerFactoryBean factory, EndpointDescription epd) {
                throw new TestException();
            }
        };
        handler.setIntentManager(intentManager);
        handler.setHttpServiceManager(dummyHttpServiceManager());
        handler.activate(dswContext);

        Map<String, Object> props = new HashMap<String, Object>();

        Runnable myService = EasyMock.createMock(Runnable.class);
        EasyMock.replay(myService);
        try {
            handler.exportService(myService, null, props, new Class[] {Runnable.class});
            fail("Expected TestException");
        } catch (TestException e) {
            // Expected
        }
    }

    private ServerFactoryBean createMockServerFactoryBean() {
        ReflectionServiceFactoryBean sf = EasyMock.createNiceMock(ReflectionServiceFactoryBean.class);
        EasyMock.replay(sf);

        final StringBuilder serverURI = new StringBuilder();

        ServerFactoryBean sfb = EasyMock.createNiceMock(ServerFactoryBean.class);
        Server server = createMockServer(sfb);

        EasyMock.expect(sfb.getServiceFactory()).andReturn(sf).anyTimes();
        EasyMock.expect(sfb.create()).andReturn(server);
        sfb.setAddress((String)EasyMock.anyObject());
        EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
            public Object answer() throws Throwable {
                serverURI.setLength(0);
                serverURI.append(EasyMock.getCurrentArguments()[0]);
                return null;
            }
        });
        EasyMock.expect(sfb.getAddress()).andAnswer(new IAnswer<String>() {
            public String answer() throws Throwable {
                return serverURI.toString();
            }
        });
        EasyMock.replay(sfb);
        return sfb;
    }

    private Server createMockServer(final ServerFactoryBean sfb) {
        AttributedURIType addr = EasyMock.createMock(AttributedURIType.class);
        EasyMock.expect(addr.getValue()).andAnswer(new IAnswer<String>() {
            public String answer() throws Throwable {
                return sfb.getAddress();
            }
        });
        EasyMock.replay(addr);

        EndpointReferenceType er = EasyMock.createMock(EndpointReferenceType.class);
        EasyMock.expect(er.getAddress()).andReturn(addr);
        EasyMock.replay(er);

        Destination destination = EasyMock.createMock(Destination.class);
        EasyMock.expect(destination.getAddress()).andReturn(er);
        EasyMock.replay(destination);

        Server server = EasyMock.createNiceMock(Server.class);
        EasyMock.expect(server.getDestination()).andReturn(destination);
        EasyMock.replay(server);
        return server;
    }

    public void testCreateEndpointProps() {
        BundleContext bc = EasyMock.createNiceMock(BundleContext.class);
        EasyMock.expect(bc.getProperty("org.osgi.framework.uuid")).andReturn("some_uuid1");
        EasyMock.replay(bc);

        IntentManager intentManager = new IntentManagerImpl();
        WsProvider pch = new WsProvider();
        pch.setIntentManager(intentManager);
        pch.setHttpServiceManager(dummyHttpServiceManager());
        pch.activate(bc);
        Class<?>[] exportedInterfaces = new Class[] {String.class};
        Map<String, Object> sd = new HashMap<String, Object>();
        sd.put(org.osgi.framework.Constants.SERVICE_ID, 42);
        EndpointHelper.addObjectClass(sd, exportedInterfaces);
        List<String> intents = Arrays.asList("my_intent", "your_intent");
        EndpointDescription epd = pch.createEndpointDesc(sd, 
                                                         new String[] {"org.apache.cxf.ws"}, 
                                                         "http://localhost:12345", 
                                                         intents);

        assertEquals("http://localhost:12345", epd.getId());
        assertEquals(Arrays.asList("java.lang.String"), epd.getInterfaces());
        assertEquals(Arrays.asList("org.apache.cxf.ws"), epd.getConfigurationTypes());
        assertEquals(Arrays.asList("my_intent", "your_intent"), epd.getIntents());
        assertEquals(new Version("0.0.0"), epd.getPackageVersion("java.lang"));
    }

    public void t2estCreateJaxWsEndpointWithoutIntents() {
        IMocksControl c = EasyMock.createNiceControl();
        BundleContext dswBC = c.createMock(BundleContext.class);

        IntentManager intentManager = new IntentManagerImpl();
        WsProvider handler = new WsProvider();
        handler.setIntentManager(intentManager);
        handler.setHttpServiceManager(dummyHttpServiceManager());
        handler.activate(dswBC);

        Map<String, Object> sd = new HashMap<String, Object>();
        sd.put(WsConstants.WS_ADDRESS_PROPERTY, "/somewhere");
        BundleContext serviceBC = c.createMock(BundleContext.class);
        Object myService = null;
        c.replay();

        Class<?>[] ifaces = new Class[] {MyJaxWsEchoService.class};
        ServerEndpoint serverWrapper = (ServerEndpoint)handler.exportService(myService, serviceBC, sd,
                                                                             ifaces);
        c.verify();

        org.apache.cxf.endpoint.Endpoint ep = serverWrapper.getServer().getEndpoint();
        QName bindingName = ep.getEndpointInfo().getBinding().getName();
        Assert.assertEquals(JaxWsEndpointImpl.class, ep.getClass());
        Assert.assertEquals(new QName("http://jaxws.handlers.dsw.dosgi.cxf.apache.org/",
                                      "MyJaxWsEchoServiceServiceSoapBinding"),
                            bindingName);
    }

    public void testCreateSimpleEndpointWithoutIntents() {
        IMocksControl c = EasyMock.createNiceControl();
        BundleContext dswBC = c.createMock(BundleContext.class);

        IntentManager intentManager = new IntentManagerImpl();
        WsProvider handler = new WsProvider();
        handler.setIntentManager(intentManager);
        handler.setHttpServiceManager(dummyHttpServiceManager());
        handler.activate(dswBC);
        Map<String, Object> sd = new HashMap<String, Object>();
        sd.put(Constants.OBJECTCLASS, new String[]{MySimpleEchoService.class.getName()});
        sd.put(WsConstants.WS_ADDRESS_PROPERTY, "/somewhere_else");
        BundleContext serviceBC = c.createMock(BundleContext.class);
        c.replay();
        Class<?>[] ifaces = new Class[] {MySimpleEchoService.class};
        ServerEndpoint serverWrapper = (ServerEndpoint)handler.exportService(null, serviceBC, sd, ifaces);
        c.verify();

        org.apache.cxf.endpoint.Endpoint ep = serverWrapper.getServer().getEndpoint();
        QName bindingName = ep.getEndpointInfo().getBinding().getName();
        Assert.assertEquals(EndpointImpl.class, ep.getClass());
        Assert.assertEquals(new QName("http://simple.handlers.dsw.dosgi.cxf.apache.org/",
                                      "MySimpleEchoServiceSoapBinding"),
                            bindingName);
    }

    @SuppressWarnings("serial")
    public static class TestException extends RuntimeException {
    }
}
