/*
 * Copyright 2015-present Open Networking Laboratory
 *
 * Licensed 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.onosproject.incubator.rpc.grpc;

import static org.junit.Assert.*;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.PortNumber.portNumber;

import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestTools;
import org.onlab.packet.ChassisId;
import org.onosproject.incubator.rpc.RemoteServiceContext;
import org.onosproject.incubator.rpc.RemoteServiceContextProvider;
import org.onosproject.incubator.rpc.RemoteServiceContextProviderService;
import org.onosproject.incubator.rpc.RemoteServiceProviderRegistry;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device.Type;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceProvider;
import org.onosproject.net.device.DeviceProviderRegistry;
import org.onosproject.net.device.DeviceProviderService;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.device.PortStatistics;
import org.onosproject.net.link.DefaultLinkDescription;
import org.onosproject.net.link.LinkDescription;
import org.onosproject.net.link.LinkProvider;
import org.onosproject.net.link.LinkProviderRegistry;
import org.onosproject.net.link.LinkProviderService;
import org.onosproject.net.provider.AbstractProviderRegistry;
import org.onosproject.net.provider.AbstractProviderService;
import org.onosproject.net.provider.ProviderId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ImmutableList;

/**
 * Set of tests of the gRPC RemoteService components.
 */
public class GrpcRemoteServiceTest {

    private static final DeviceId DEVICE_ID = deviceId("dev:000001");

    private final Logger log = LoggerFactory.getLogger(getClass());

    private static final ProviderId PID = new ProviderId("test", "com.exmaple.test");

    private static final URI DURI = URI.create("dev:000001");

    private static final String MFR = "mfr";

    private static final String HW = "hw";

    private static final String SW = "sw";

    private static final String SN = "serial";

    private static final ChassisId CHASSIS = new ChassisId(42);

    private static final SparseAnnotations ANON = DefaultAnnotations.builder()
                                                    .set("foo", "var")
                                                    .build();

    private static final PortNumber PORT = PortNumber.portNumber(99);

    private static final DeviceDescription DDESC
        = new DefaultDeviceDescription(DURI, Type.SWITCH, MFR, HW, SW, SN,
                                       CHASSIS, ANON);

    private GrpcRemoteServiceServer server;
    private GrpcRemoteServiceProvider client;

    private DeviceProvider svSideDeviceProvider;

    private MTestDeviceProviderService svDeviceProviderService;

    private ServerSideLinkProviderService svLinkProviderService;


    private CountDownLatch serverReady;

    private URI uri;

    @Before
    public void setUp() throws Exception {
        serverReady = new CountDownLatch(1);
        server = new GrpcRemoteServiceServer();
        server.deviceProviderRegistry = new MTestDeviceProviderRegistry();
        server.linkProviderRegistry = new ServerSideLinkProviderRegistry();
        server.listenPort = TestTools.findAvailablePort(11984);
        uri = URI.create("grpc://localhost:" + server.listenPort);
        // todo: pass proper ComponentContext
        server.activate(null);

        client = new GrpcRemoteServiceProvider();
        client.rpcRegistry = new NoOpRemoteServiceProviderRegistry();
        client.activate();
    }

    @After
    public void tearDown() {
        client.deactivate();
        server.deactivate();
        svLinkProviderService = null;
    }

    private static void assertEqualsButNotSame(Object expected, Object actual) {
        assertEquals(expected, actual);
        assertNotSame("Cannot be same instance if it properly went through gRPC",
                      expected, actual);
    }

    @Test
    public void deviceServiceBasics() throws InterruptedException {
        RemoteServiceContext remoteServiceContext = client.get(uri);
        assertNotNull(remoteServiceContext);

        DeviceProviderRegistry deviceProviderRegistry = remoteServiceContext.get(DeviceProviderRegistry.class);
        assertNotNull(deviceProviderRegistry);

        CTestDeviceProvider clDeviceProvider = new CTestDeviceProvider();
        DeviceProviderService clDeviceProviderService = deviceProviderRegistry.register(clDeviceProvider);

        assertTrue(serverReady.await(10, TimeUnit.SECONDS));

        // client to server communication
        clDeviceProviderService.deviceConnected(DEVICE_ID, DDESC);
        assertTrue(svDeviceProviderService.deviceConnected.await(10, TimeUnit.SECONDS));
        assertEqualsButNotSame(DEVICE_ID, svDeviceProviderService.deviceConnectedDid);
        assertEqualsButNotSame(DDESC, svDeviceProviderService.deviceConnectedDesc);

        PortDescription portDescription = new DefaultPortDescription(PORT, true, ANON);
        List<PortDescription> portDescriptions = ImmutableList.of(portDescription);
        clDeviceProviderService.updatePorts(DEVICE_ID, portDescriptions);
        assertTrue(svDeviceProviderService.updatePorts.await(10, TimeUnit.SECONDS));
        assertEqualsButNotSame(DEVICE_ID, svDeviceProviderService.updatePortsDid);
        assertEqualsButNotSame(portDescriptions, svDeviceProviderService.updatePortsDescs);

        MastershipRole cRole = MastershipRole.MASTER;
        MastershipRole dRole = MastershipRole.STANDBY;
        clDeviceProviderService.receivedRoleReply(DEVICE_ID, cRole, dRole);
        assertTrue(svDeviceProviderService.receivedRoleReply.await(10, TimeUnit.SECONDS));
        assertEqualsButNotSame(DEVICE_ID, svDeviceProviderService.receivedRoleReplyDid);
        assertEquals(cRole, svDeviceProviderService.receivedRoleReplyRequested);
        assertEquals(dRole, svDeviceProviderService.receivedRoleReplyResponse);

        clDeviceProviderService.portStatusChanged(DEVICE_ID, portDescription);
        assertTrue(svDeviceProviderService.portStatusChanged.await(10, TimeUnit.SECONDS));
        assertEqualsButNotSame(DEVICE_ID, svDeviceProviderService.portStatusChangedDid);
        assertEqualsButNotSame(portDescription, svDeviceProviderService.portStatusChangedDesc);

        Collection<PortStatistics> portStatistics = Collections.emptyList();
        clDeviceProviderService.updatePortStatistics(DEVICE_ID, portStatistics);
        assertTrue(svDeviceProviderService.updatePortStatistics.await(10, TimeUnit.SECONDS));
        assertEqualsButNotSame(DEVICE_ID, svDeviceProviderService.updatePortStatisticsDid);
        assertEqualsButNotSame(portStatistics, svDeviceProviderService.updatePortStatisticsStats);

        clDeviceProviderService.deviceDisconnected(DEVICE_ID);
        assertTrue(svDeviceProviderService.deviceDisconnected.await(10, TimeUnit.SECONDS));
        assertEqualsButNotSame(DEVICE_ID, svDeviceProviderService.deviceDisconnectedDid);



        // server to client communication
        svSideDeviceProvider.triggerProbe(DEVICE_ID);
        assertTrue(clDeviceProvider.triggerProbe.await(10, TimeUnit.SECONDS));
        assertEquals(DEVICE_ID, clDeviceProvider.triggerProbeDid);
        assertNotSame("Cannot be same instance if it properly went through gRPC",
                      DEVICE_ID, clDeviceProvider.triggerProbeDid);

        svSideDeviceProvider.roleChanged(DEVICE_ID, MastershipRole.STANDBY);
        assertTrue(clDeviceProvider.roleChanged.await(10, TimeUnit.SECONDS));
        assertEquals(DEVICE_ID, clDeviceProvider.roleChangedDid);
        assertNotSame("Cannot be same instance if it properly went through gRPC",
                      DEVICE_ID, clDeviceProvider.roleChangedDid);
        assertEquals(MastershipRole.STANDBY, clDeviceProvider.roleChangedNewRole);

        clDeviceProvider.isReachableReply = false;
        assertEquals(clDeviceProvider.isReachableReply,
                     svSideDeviceProvider.isReachable(DEVICE_ID));
        assertTrue(clDeviceProvider.isReachable.await(10, TimeUnit.SECONDS));
        assertEquals(DEVICE_ID, clDeviceProvider.isReachableDid);
        assertNotSame("Cannot be same instance if it properly went through gRPC",
                      DEVICE_ID, clDeviceProvider.isReachableDid);
    }

    @Test
    public void linkVanishedDevice() throws InterruptedException {
        RemoteServiceContext remoteServiceContext = client.get(uri);
        assertNotNull(remoteServiceContext);

        LinkProviderRegistry providerRegistry = remoteServiceContext.get(LinkProviderRegistry.class);
        assertNotNull(providerRegistry);

        final String schemeTest = "test";
        LinkProviderService client = providerRegistry.register(new StubLinkProvider(schemeTest));
        assertNotNull(client);

        client.linksVanished(DEVICE_ID);

        assertEquals(schemeTest, svLinkProviderService.provider().id().scheme());
        assertTrue(svLinkProviderService.calls.await(10, TimeUnit.SECONDS));
        assertEqualsButNotSame(DEVICE_ID, svLinkProviderService.arg);
    }

    @Test
    public void linkVanishedPort() throws InterruptedException {
        RemoteServiceContext remoteServiceContext = client.get(uri);
        assertNotNull(remoteServiceContext);

        LinkProviderRegistry providerRegistry = remoteServiceContext.get(LinkProviderRegistry.class);
        assertNotNull(providerRegistry);

        final String schemeTest = "test";
        LinkProviderService client = providerRegistry.register(new StubLinkProvider(schemeTest));
        assertNotNull(client);


        final ConnectPoint cp = new ConnectPoint(DEVICE_ID, PORT);
        client.linksVanished(cp);
        assertEquals(schemeTest, svLinkProviderService.provider().id().scheme());
        assertTrue(svLinkProviderService.calls.await(10, TimeUnit.SECONDS));
        assertEqualsButNotSame(cp, svLinkProviderService.arg);
    }

    @Test
    public void linkVanishedDescription() throws InterruptedException {
        RemoteServiceContext remoteServiceContext = client.get(uri);
        assertNotNull(remoteServiceContext);

        LinkProviderRegistry providerRegistry = remoteServiceContext.get(LinkProviderRegistry.class);
        assertNotNull(providerRegistry);

        final String schemeTest = "test";
        LinkProviderService client = providerRegistry.register(new StubLinkProvider(schemeTest));
        assertNotNull(client);

        ConnectPoint src = new ConnectPoint(deviceId("dev:1"), portNumber(10));
        ConnectPoint dst = new ConnectPoint(deviceId("dev:2"), portNumber(20));
        LinkDescription linkDescription = new DefaultLinkDescription(src, dst, Link.Type.DIRECT, ANON);
        client.linkVanished(linkDescription);
        assertEquals(schemeTest, svLinkProviderService.provider().id().scheme());
        assertTrue(svLinkProviderService.calls.await(10, TimeUnit.SECONDS));
        assertEqualsButNotSame(linkDescription, svLinkProviderService.arg);
    }

    @Test
    public void linkDetected() throws InterruptedException {
        RemoteServiceContext remoteServiceContext = client.get(uri);
        assertNotNull(remoteServiceContext);

        LinkProviderRegistry providerRegistry = remoteServiceContext.get(LinkProviderRegistry.class);
        assertNotNull(providerRegistry);

        final String schemeTest = "test";
        LinkProviderService client = providerRegistry.register(new StubLinkProvider(schemeTest));
        assertNotNull(client);

        ConnectPoint src = new ConnectPoint(deviceId("dev:1"), portNumber(10));
        ConnectPoint dst = new ConnectPoint(deviceId("dev:2"), portNumber(20));
        LinkDescription linkDescription = new DefaultLinkDescription(src, dst, Link.Type.DIRECT, ANON);
        client.linkDetected(linkDescription);
        assertEquals(schemeTest, svLinkProviderService.provider().id().scheme());
        assertTrue(svLinkProviderService.calls.await(10, TimeUnit.SECONDS));
        assertEqualsButNotSame(linkDescription, svLinkProviderService.arg);
    }

    @Test
    public void linkServiceBasics() throws InterruptedException {
        RemoteServiceContext remoteServiceContext = client.get(uri);
        assertNotNull(remoteServiceContext);

        LinkProviderRegistry providerRegistry = remoteServiceContext.get(LinkProviderRegistry.class);
        assertNotNull(providerRegistry);

        final String schemeTest = "test";
        LinkProviderService client = providerRegistry.register(new StubLinkProvider(schemeTest));
        assertNotNull(client);

        ConnectPoint src = new ConnectPoint(deviceId("dev:1"), portNumber(10));
        ConnectPoint dst = new ConnectPoint(deviceId("dev:2"), portNumber(20));
        LinkDescription linkDescription = new DefaultLinkDescription(src, dst, Link.Type.DIRECT, ANON);

        client.linkDetected(linkDescription);
        assertEquals(schemeTest, svLinkProviderService.provider().id().scheme());
        assertTrue(svLinkProviderService.calls.await(10, TimeUnit.SECONDS));
        assertEqualsButNotSame(linkDescription, svLinkProviderService.arg);

        svLinkProviderService.reset();

        client.linkVanished(linkDescription);
        assertEquals(schemeTest, svLinkProviderService.provider().id().scheme());
        assertTrue(svLinkProviderService.calls.await(10, TimeUnit.SECONDS));
        assertEqualsButNotSame(linkDescription, svLinkProviderService.arg);
    }

    /**
     * Device Provider on CO side.
     */
    public class CTestDeviceProvider implements DeviceProvider {

        final CountDownLatch triggerProbe = new CountDownLatch(1);
        DeviceId triggerProbeDid;

        final CountDownLatch roleChanged = new CountDownLatch(1);
        DeviceId roleChangedDid;
        MastershipRole roleChangedNewRole;

        final CountDownLatch isReachable = new CountDownLatch(1);
        DeviceId isReachableDid;
        boolean isReachableReply = false;

        final CountDownLatch portStateChanged = new CountDownLatch(1);
        DeviceId portStateChangedDid;
        PortNumber portStateChangedPort;

        @Override
        public ProviderId id() {
            return PID;
        }

        @Override
        public void triggerProbe(DeviceId deviceId) {
            log.info("triggerProbe({}) on Client called", deviceId);
            triggerProbeDid = deviceId;
            triggerProbe.countDown();
        }

        @Override
        public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
            log.info("roleChanged({},{}) on Client called", deviceId, newRole);
            roleChangedDid = deviceId;
            roleChangedNewRole = newRole;
            roleChanged.countDown();
        }

        @Override
        public boolean isReachable(DeviceId deviceId) {
            log.info("isReachable({}) on Client called", deviceId);
            isReachableDid = deviceId;
            isReachable.countDown();
            return isReachableReply;
        }

        @Override
        public void changePortState(DeviceId deviceId, PortNumber portNumber,
                                    boolean enable) {
            log.info("portState change to {} on ({},{}) on Client called", enable,
                     deviceId, portNumber);
            portStateChangedDid = deviceId;
            portStateChangedPort = portNumber;
            portStateChanged.countDown();

        }

    }

    class NoOpRemoteServiceProviderRegistry
        implements RemoteServiceProviderRegistry {

        @Override
        public RemoteServiceContextProviderService register(RemoteServiceContextProvider provider) {
            return new RemoteServiceContextProviderService() {

                @Override
                public RemoteServiceContextProvider provider() {
                    return provider;
                }
            };
        }

        @Override
        public void unregister(RemoteServiceContextProvider provider) {
        }

        @Override
        public Set<ProviderId> getProviders() {
            return Collections.emptySet();
        }
    }

    /**
     * DeviceProvider on Metro side.
     */
    public class MTestDeviceProviderRegistry
        extends AbstractProviderRegistry<DeviceProvider, DeviceProviderService>
        implements DeviceProviderRegistry {

        @Override
        protected DeviceProviderService createProviderService(DeviceProvider provider) {
            log.info("createProviderService({})", provider);
            svSideDeviceProvider = provider;
            svDeviceProviderService = new MTestDeviceProviderService(provider);
            serverReady.countDown();
            return svDeviceProviderService;
        }

    }

    private final class MTestDeviceProviderService
            extends AbstractProviderService<DeviceProvider>
            implements DeviceProviderService {

        public MTestDeviceProviderService(DeviceProvider provider) {
            super(provider);
        }


        final CountDownLatch deviceConnected = new CountDownLatch(1);
        DeviceId deviceConnectedDid;
        DeviceDescription deviceConnectedDesc;

        @Override
        public void deviceConnected(DeviceId deviceId,
                                    DeviceDescription deviceDescription) {
            log.info("deviceConnected({}, {}) on Server called", deviceId, deviceDescription);
            deviceConnectedDid = deviceId;
            deviceConnectedDesc = deviceDescription;
            deviceConnected.countDown();
        }


        final CountDownLatch updatePorts = new CountDownLatch(1);
        DeviceId updatePortsDid;
        List<PortDescription> updatePortsDescs;

        @Override
        public void updatePorts(DeviceId deviceId,
                                List<PortDescription> portDescriptions) {
            log.info("updatePorts({}, {}) on Server called", deviceId, portDescriptions);
            updatePortsDid = deviceId;
            updatePortsDescs = portDescriptions;
            updatePorts.countDown();
        }

        final CountDownLatch receivedRoleReply = new CountDownLatch(1);
        DeviceId receivedRoleReplyDid;
        MastershipRole receivedRoleReplyRequested;
        MastershipRole receivedRoleReplyResponse;

        @Override
        public void receivedRoleReply(DeviceId deviceId, MastershipRole requested,
                                      MastershipRole response) {
            log.info("receivedRoleReply({}, {}, {}) on Server called", deviceId, requested, response);
            receivedRoleReplyDid = deviceId;
            receivedRoleReplyRequested = requested;
            receivedRoleReplyResponse = response;
            receivedRoleReply.countDown();
        }

        final CountDownLatch portStatusChanged = new CountDownLatch(1);
        DeviceId portStatusChangedDid;
        PortDescription portStatusChangedDesc;


        @Override
        public void portStatusChanged(DeviceId deviceId,
                                      PortDescription portDescription) {
            log.info("portStatusChanged({}, {}) on Server called", deviceId, portDescription);
            portStatusChangedDid = deviceId;
            portStatusChangedDesc = portDescription;
            portStatusChanged.countDown();
        }

        final CountDownLatch updatePortStatistics = new CountDownLatch(1);
        DeviceId updatePortStatisticsDid;
        Collection<PortStatistics> updatePortStatisticsStats;


        @Override
        public void updatePortStatistics(DeviceId deviceId,
                                         Collection<PortStatistics> portStatistics) {
            log.info("updatePortStatistics({}, {}) on Server called", deviceId, portStatistics);
            updatePortStatisticsDid = deviceId;
            updatePortStatisticsStats = portStatistics;
            updatePortStatistics.countDown();
        }

        final CountDownLatch deviceDisconnected = new CountDownLatch(1);
        DeviceId deviceDisconnectedDid;

        @Override
        public void deviceDisconnected(DeviceId deviceId) {
            log.info("deviceDisconnected({}) on Server called", deviceId);
            deviceDisconnectedDid = deviceId;
            deviceDisconnected.countDown();
        }
    }

    public class ServerSideLinkProviderRegistry
            extends AbstractProviderRegistry<LinkProvider, LinkProviderService>
            implements LinkProviderRegistry {

        @Override
        protected LinkProviderService createProviderService(LinkProvider provider) {
            svLinkProviderService = new ServerSideLinkProviderService(provider);
            return svLinkProviderService;
        }

    }

    public class ServerSideLinkProviderService
            extends AbstractProviderService<LinkProvider>
            implements LinkProviderService {

        CountDownLatch calls = new CountDownLatch(1);
        Object arg = null;

        public void reset() {
            calls = new CountDownLatch(1);
            arg = null;
        }

        public ServerSideLinkProviderService(LinkProvider provider) {
            super(provider);
        }

        @Override
        public void linksVanished(DeviceId deviceId) {
            log.info("linksVanished({})", deviceId);
            arg = deviceId;
            calls.countDown();
        }

        @Override
        public void linksVanished(ConnectPoint connectPoint) {
            log.info("linksVanished({})", connectPoint);
            arg = connectPoint;
            calls.countDown();
        }

        @Override
        public void linkVanished(LinkDescription linkDescription) {
            log.info("linksVanished({})", linkDescription);
            arg = linkDescription;
            calls.countDown();
        }

        @Override
        public void linkDetected(LinkDescription linkDescription) {
            log.info("linkDetected({})", linkDescription);
            arg = linkDescription;
            calls.countDown();
        }
    }

}
