/*
 * 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.ignite.internal.client.thin;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.apache.ignite.Ignite;
import org.apache.ignite.client.ClientClusterGroup;
import org.apache.ignite.client.ClientException;
import org.apache.ignite.client.ClientServiceDescriptor;
import org.apache.ignite.client.IgniteClient;
import org.apache.ignite.client.Person;
import org.apache.ignite.internal.binary.BinaryArray;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.platform.PlatformType;
import org.apache.ignite.resources.IgniteInstanceResource;
import org.apache.ignite.resources.ServiceContextResource;
import org.apache.ignite.services.Service;
import org.apache.ignite.services.ServiceCallContext;
import org.apache.ignite.services.ServiceCallContextBuilder;
import org.apache.ignite.services.ServiceCallInterceptor;
import org.apache.ignite.services.ServiceConfiguration;
import org.apache.ignite.services.ServiceContext;
import org.apache.ignite.testframework.GridTestUtils;
import org.junit.Test;

import static org.apache.ignite.IgniteSystemProperties.IGNITE_USE_BINARY_ARRAYS;
import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause;
import static org.junit.Assert.assertArrayEquals;

/**
 * Checks service invocation for thin client.
 */
public class ServicesTest extends AbstractThinClientTest {
    /** Node-id service name. */
    private static final String NODE_ID_SERVICE_NAME = "node_id_svc";

    /** Node-singleton service name. */
    private static final String NODE_SINGLTON_SERVICE_NAME = "node_svc";

    /** Cluster-singleton service name. */
    private static final String CLUSTER_SINGLTON_SERVICE_NAME = "cluster_svc";

    /** */
    protected boolean useBinaryArrays;

    /** {@inheritDoc} */
    @Override protected void beforeTestsStarted() throws Exception {
        super.beforeTestsStarted();

        System.setProperty(IGNITE_USE_BINARY_ARRAYS, Boolean.toString(useBinaryArrays));
        BinaryArray.initUseBinaryArrays();

        startGrids(3);

        startClientGrid(3);

        grid(0).createCache(DEFAULT_CACHE_NAME);

        awaitPartitionMapExchange();

        grid(0).services().deployNodeSingleton(NODE_ID_SERVICE_NAME, new TestNodeIdService());

        ServiceConfiguration svcCfg = new ServiceConfiguration()
            .setName(NODE_SINGLTON_SERVICE_NAME)
            .setService(new TestService())
            .setMaxPerNodeCount(1)
            .setInterceptors(new TestServiceInterceptor());

        grid(0).services().deploy(svcCfg);

        // Deploy CLUSTER_SINGLTON_SERVICE_NAME to grid(1).
        int keyGrid1 = primaryKey(grid(1).cache(DEFAULT_CACHE_NAME));

        grid(0).services().deployKeyAffinitySingleton(CLUSTER_SINGLTON_SERVICE_NAME, new TestService(),
            DEFAULT_CACHE_NAME, keyGrid1);
    }

    /** {@inheritDoc} */
    @Override protected void afterTestsStopped() throws Exception {
        super.afterTestsStopped();

        System.clearProperty(IGNITE_USE_BINARY_ARRAYS);
        BinaryArray.initUseBinaryArrays();
    }

    /**
     * Test that overloaded methods resolved correctly.
     */
    @Test
    public void testOverloadedMethods() throws Exception {
        try (IgniteClient client = startClient(0)) {
            // Test local service calls (service deployed to each node).
            TestServiceInterface svc = client.services().serviceProxy(NODE_SINGLTON_SERVICE_NAME,
                TestServiceInterface.class);

            checkOverloadedMethods(svc);

            // Test remote service calls (client connected to grid(0) but service deployed to grid(1)).
            svc = client.services().serviceProxy(CLUSTER_SINGLTON_SERVICE_NAME, TestServiceInterface.class);

            checkOverloadedMethods(svc);
        }
    }

    /**
     * @param svc Service.
     */
    private void checkOverloadedMethods(TestServiceInterface svc) {
        assertEquals("testMethod()", svc.testMethod());

        assertEquals("testMethod(String val): test", svc.testMethod("test"));

        assertEquals(123, svc.testMethod(123));

        assertEquals("testMethod(Object val): test", svc.testMethod(new StringBuilder("test")));

        assertEquals("testMethod(String val): null", svc.testMethod((String)null));

        assertEquals("testMethod(Object val): null", svc.testMethod((Object)null));

        Person person1 = new Person(1, "Person 1");
        Person person2 = new Person(2, "Person 2");

        assertEquals("testMethod(Person person, Object obj): " + person1 + ", " + person2,
            svc.testMethod(person1, (Object)person2));

        assertEquals("testMethod(Object obj, Person person): " + person1 + ", " + person2,
            svc.testMethod((Object)person1, person2));
    }

    /**
     * Test that methods which get and return collections work correctly.
     */
    @Test
    public void testCollectionMethods() throws Exception {
        try (IgniteClient client = startClient(0)) {
            // Test local service calls (service deployed to each node).
            TestServiceInterface svc = client.services().serviceProxy(NODE_SINGLTON_SERVICE_NAME,
                TestServiceInterface.class);

            checkCollectionMethods(svc);

            // Test remote service calls (client connected to grid(0) but service deployed to grid(1)).
            svc = client.services().serviceProxy(CLUSTER_SINGLTON_SERVICE_NAME, TestServiceInterface.class);

            checkCollectionMethods(svc);
        }
    }

    /**
     * @param svc Service.
     */
    private void checkCollectionMethods(TestServiceInterface svc) {
        Person person1 = new Person(1, "Person 1");
        Person person2 = new Person(2, "Person 2");

        Person[] arr = new Person[] {person1, person2};
        assertTrue(Arrays.equals(arr, svc.testArray(arr)));

        Collection<Person> col = new HashSet<>(F.asList(person1, person2));
        assertEquals(col, svc.testCollection(col));

        Map<Integer, Person> map = F.asMap(1, person1, 2, person2);
        assertEquals(map, svc.testMap(map));
    }

    /**
     * Test that exception is thrown when invoking service with wrong interface.
     */
    @Test
    public void testWrongMethodInvocation() throws Exception {
        try (IgniteClient client = startClient(0)) {
            TestServiceInterface svc = client.services().serviceProxy(NODE_ID_SERVICE_NAME,
                TestServiceInterface.class);

            GridTestUtils.assertThrowsAnyCause(log, () -> svc.testMethod(0), ClientException.class,
                "Method not found");
        }
    }

    /**
     * Test that exception is thrown when trying to invoke non-existing service.
     */
    @Test
    public void testWrongServiceName() throws Exception {
        try (IgniteClient client = startClient(0)) {
            TestServiceInterface svc = client.services().serviceProxy("no_such_service",
                TestServiceInterface.class);

            GridTestUtils.assertThrowsAnyCause(log, () -> svc.testMethod(0), ClientException.class,
                "Service not found");
        }
    }

    /**
     * Test that service exception message is propagated to client.
     */
    @Test
    public void testServiceException() throws Exception {
        try (IgniteClient client = startClient(0)) {
            // Test local service calls (service deployed to each node).
            TestServiceInterface svc = client.services().serviceProxy(NODE_SINGLTON_SERVICE_NAME,
                TestServiceInterface.class);

            GridTestUtils.assertThrowsAnyCause(log, svc::testException, ClientException.class,
                "testException()");

            // Test remote service calls (client connected to grid(0) but service deployed to grid(1)).
            client.services().serviceProxy(CLUSTER_SINGLTON_SERVICE_NAME, TestServiceInterface.class);

            GridTestUtils.assertThrowsAnyCause(log, svc::testException, ClientException.class,
                "testException()");
        }
    }

    /** Test custom caller context. */
    @Test
    public void testServiceCallContext() {
        String attrName = "testAttr";
        String attrVal = "test";
        String binAttrName = "binTestAttr";
        byte[] binAttrVal = attrVal.getBytes();

        try (IgniteClient client = startClient(0)) {
            // Check proxy creation with an invalid implementation.
            ServiceCallContext customCls = new ServiceCallContext() {
                @Override public String attribute(String name) {
                    return null;
                }

                @Override public byte[] binaryAttribute(String name) {
                    return null;
                }
            };

            GridTestUtils.assertThrowsAnyCause(log, () -> client.services().serviceProxy(NODE_SINGLTON_SERVICE_NAME,
                TestServiceInterface.class, customCls), IllegalArgumentException.class, "\"callCtx\" has an invalid type.");

            // Check proxy creation with a valid caller context.
            ServiceCallContext callCtx = new ServiceCallContextBuilder()
                .put(attrName, attrVal)
                .put(binAttrName, binAttrVal)
                .build();

            TestServiceInterface svc = client.services().serviceProxy(NODE_SINGLTON_SERVICE_NAME,
                TestServiceInterface.class, callCtx);

            assertEquals(attrVal, svc.testContextAttribute(attrName));
            assertArrayEquals(binAttrVal, svc.testContextBinaryAttribute(binAttrName));
        }
    }

    /** Test service call interceptor. */
    @Test
    public void testServiceInterceptor() {
        try (IgniteClient client = startClient(0)) {
            TestServiceInterface svc = client.services().serviceProxy(NODE_SINGLTON_SERVICE_NAME, TestServiceInterface.class);

            int val = TestServiceInterceptor.INTERCEPTED_VALUE;

            assertEquals(val * val, svc.testMethod(val));
            assertEquals(val + 1, svc.testMethod(val + 1));
        }
    }

    /**
     * Test that services executed on cluster group.
     */
    @Test
    public void testServicesOnClusterGroup() throws Exception {
        try (IgniteClient client = startClient(0)) {
            // Local node.
            ClientClusterGroup grp = client.cluster().forNodeId(nodeId(0), nodeId(3));

            TestNodeIdServiceInterface nodeSvc0 = client.services(grp).serviceProxy(NODE_ID_SERVICE_NAME,
                TestNodeIdServiceInterface.class);

            assertEquals(nodeId(0), nodeSvc0.nodeId());

            // Remote node.
            grp = client.cluster().forNodeId(nodeId(1), nodeId(3));

            nodeSvc0 = client.services(grp).serviceProxy(NODE_ID_SERVICE_NAME,
                TestNodeIdServiceInterface.class);

            assertEquals(nodeId(1), nodeSvc0.nodeId());

            // Client node.
            grp = client.cluster().forNodeId(nodeId(3));

            TestNodeIdServiceInterface nodeSvc1 = client.services(grp).serviceProxy(NODE_ID_SERVICE_NAME,
                TestNodeIdServiceInterface.class);

            GridTestUtils.assertThrowsAnyCause(log, nodeSvc1::nodeId, ClientException.class,
                "Failed to find deployed service");

            // All nodes, except service node.
            grp = client.cluster().forNodeId(nodeId(0), nodeId(2), nodeId(3));

            TestServiceInterface nodeSvc2 = client.services(grp).serviceProxy(CLUSTER_SINGLTON_SERVICE_NAME,
                TestServiceInterface.class);

            GridTestUtils.assertThrowsAnyCause(log, nodeSvc2::testMethod, ClientException.class,
                "Failed to find deployed service");
        }
    }

    /**
     * Test services timeout.
     */
    @Test
    public void testServiceTimeout() throws Exception {
        long timeout = 100L;

        try (IgniteClient client = startClient(0)) {
            TestServiceInterface svc = client.services().serviceProxy(CLUSTER_SINGLTON_SERVICE_NAME,
                TestServiceInterface.class, timeout);

            TestService.latch = new CountDownLatch(1);

            GridTestUtils.assertThrowsAnyCause(log, svc::waitLatch, ClientException.class, "timed out");
        }
        finally {
            if (TestService.latch != null) {
                TestService.latch.countDown();
                TestService.latch = null;
            }
        }
    }

    /** Test service descriptors returned correctly. */
    @Test
    public void testServiceDescriptors() throws Exception {
        try (IgniteClient client = startClient(0)) {
            Collection<ClientServiceDescriptor> svcs = client.services().serviceDescriptors();

            assertNotNull(svcs);

            assertEquals(3, svcs.size());

            assertTrue(svcs.stream().filter(svc -> svc.name().equals(NODE_ID_SERVICE_NAME)).peek(svc -> {
                assertEquals(NODE_ID_SERVICE_NAME, svc.name());
                assertEquals(TestNodeIdService.class.getName(), svc.serviceClass());
                assertEquals(0, svc.totalCount());
                assertEquals(1, svc.maxPerNodeCount());
                assertNull(svc.cacheName());
                assertEquals(grid(0).localNode().id(), svc.originNodeId());
                assertEquals(PlatformType.JAVA, svc.platformType());

                assertDescriptorsEquals(svc, client.services().serviceDescriptor(NODE_ID_SERVICE_NAME));
            }).findFirst().isPresent());

            assertTrue(svcs.stream().filter(svc -> svc.name().equals(NODE_SINGLTON_SERVICE_NAME)).peek(svc -> {
                assertEquals(NODE_SINGLTON_SERVICE_NAME, svc.name());
                assertEquals(TestService.class.getName(), svc.serviceClass());
                assertEquals(0, svc.totalCount());
                assertEquals(1, svc.maxPerNodeCount());
                assertNull(svc.cacheName());
                assertEquals(grid(0).localNode().id(), svc.originNodeId());
                assertEquals(PlatformType.JAVA, svc.platformType());

                assertDescriptorsEquals(svc, client.services().serviceDescriptor(NODE_SINGLTON_SERVICE_NAME));
            }).findFirst().isPresent());

            assertTrue(svcs.stream().filter(svc -> svc.name().equals(CLUSTER_SINGLTON_SERVICE_NAME)).peek(svc -> {
                assertEquals(CLUSTER_SINGLTON_SERVICE_NAME, svc.name());
                assertEquals(TestService.class.getName(), svc.serviceClass());
                assertEquals(1, svc.totalCount());
                assertEquals(1, svc.maxPerNodeCount());
                assertEquals(DEFAULT_CACHE_NAME, svc.cacheName());
                assertEquals(grid(0).localNode().id(), svc.originNodeId());
                assertEquals(PlatformType.JAVA, svc.platformType());

                assertDescriptorsEquals(svc, client.services().serviceDescriptor(CLUSTER_SINGLTON_SERVICE_NAME));
            }).findFirst().isPresent());

            assertThrowsWithCause(() -> {
                client.services().serviceDescriptor("unknown");
            }, ClientException.class);
        }
    }

    /** */
    private void assertDescriptorsEquals(ClientServiceDescriptor svc, ClientServiceDescriptor svc1) {
        assertEquals(svc1.name(), svc.name());
        assertEquals(svc1.serviceClass(), svc.serviceClass());
        assertEquals(svc1.totalCount(), svc.totalCount());
        assertEquals(svc1.maxPerNodeCount(), svc.maxPerNodeCount());
        assertEquals(svc1.cacheName(), svc.cacheName());
        assertEquals(svc1.originNodeId(), svc.originNodeId());
        assertEquals(svc1.platformType(), svc.platformType());
    }

    /** */
    public static interface TestServiceInterface {
        /** */
        public String testMethod();

        /** */
        public String testMethod(String val);

        /** */
        public String testMethod(Object val);

        /** */
        public int testMethod(int val);

        /** */
        public String testMethod(Person person, Object obj);

        /** */
        public String testMethod(Object obj, Person person);

        /** */
        public Person[] testArray(Person[] persons);

        /** */
        public Collection<Person> testCollection(Collection<Person> persons);

        /** */
        public Map<Integer, Person> testMap(Map<Integer, Person> persons);

        /** */
        public Object testException();

        /** */
        public String testContextAttribute(String name);

        /** */
        public byte[] testContextBinaryAttribute(String name);

        /** */
        public boolean waitLatch() throws Exception;
    }

    /**
     * Implementation of TestServiceInterface.
     */
    public static class TestService implements Service, TestServiceInterface {
        /** Latch. */
        public static CountDownLatch latch;

        /** Service context. */
        @ServiceContextResource
        private ServiceContext svcCtx;

        /** {@inheritDoc} */
        @Override public String testMethod() {
            return "testMethod()";
        }

        /** {@inheritDoc} */
        @Override public String testMethod(String val) {
            return "testMethod(String val): " + val;
        }

        /** {@inheritDoc} */
        @Override public String testMethod(Object val) {
            return "testMethod(Object val): " + val;
        }

        /** {@inheritDoc} */
        @Override public int testMethod(int val) {
            return val;
        }

        /** {@inheritDoc} */
        @Override public String testMethod(Person person, Object obj) {
            return "testMethod(Person person, Object obj): " + person + ", " + obj;
        }

        /** {@inheritDoc} */
        @Override public String testMethod(Object obj, Person person) {
            return "testMethod(Object obj, Person person): " + obj + ", " + person;
        }

        /** {@inheritDoc} */
        @Override public Person[] testArray(Person[] persons) {
            return persons;
        }

        /** {@inheritDoc} */
        @Override public Collection<Person> testCollection(Collection<Person> persons) {
            return persons;
        }

        /** {@inheritDoc} */
        @Override public Map<Integer, Person> testMap(Map<Integer, Person> persons) {
            return persons;
        }

        /** {@inheritDoc} */
        @Override public Object testException() {
            throw new IllegalStateException("testException()");
        }

        /** {@inheritDoc} */
        @Override public String testContextAttribute(String name) {
            ServiceCallContext callCtx = svcCtx.currentCallContext();

            return callCtx == null ? null : callCtx.attribute(name);
        }

        /** {@inheritDoc} */
        @Override public byte[] testContextBinaryAttribute(String name) {
            ServiceCallContext callCtx = svcCtx.currentCallContext();

            return callCtx == null ? null : callCtx.binaryAttribute(name);
        }

        /** {@inheritDoc} */
        @Override public boolean waitLatch() throws Exception {
            latch.await(10L, TimeUnit.SECONDS);

            return true;
        }
    }

    /** */
    private static class TestServiceInterceptor implements ServiceCallInterceptor {
        /** */
        private static final long serialVersionUID = 0L;

        /** */
        private static final Integer INTERCEPTED_VALUE = 42;

        /** {@inheritDoc} */
        @Override public Object invoke(String mtd, Object[] args, ServiceContext ctx, Callable<Object> next)
            throws Exception {
            Object res = next.call();;

            if (args.length == 1 && "testMethod".equals(mtd) && Objects.equals(INTERCEPTED_VALUE, args[0]))
                return (int)res * (int)res;

            return res;
        }
    }

    /**
     * Service to return ID of node where method was executed.
     */
    public static interface TestNodeIdServiceInterface {
        /** Gets ID of node where method was executed */
        public UUID nodeId();
    }

    /**
     * Implementation of TestNodeIdServiceInterface
     */
    public static class TestNodeIdService implements Service, TestNodeIdServiceInterface {
        /** Ignite. */
        @IgniteInstanceResource
        Ignite ignite;

        /** {@inheritDoc} */
        @Override public UUID nodeId() {
            return ignite.cluster().localNode().id();
        }
    }
}
