/*
 * Copyright 2016-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.lisp.ctl.impl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.easymock.EasyMock;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.IpAddress;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.CoreService;
import org.onosproject.lisp.ctl.LispMessageListener;
import org.onosproject.lisp.ctl.LispRouter;
import org.onosproject.lisp.ctl.LispRouterAdapter;
import org.onosproject.lisp.ctl.LispRouterAgent;
import org.onosproject.lisp.ctl.LispRouterId;
import org.onosproject.lisp.ctl.LispRouterListener;
import org.onosproject.lisp.msg.protocols.DefaultLispMapNotify.DefaultNotifyBuilder;
import org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.DefaultMapRecordBuilder;
import org.onosproject.lisp.msg.protocols.DefaultLispMapRegister.DefaultRegisterBuilder;
import org.onosproject.lisp.msg.protocols.LispMapNotify;
import org.onosproject.lisp.msg.protocols.LispMapNotify.NotifyBuilder;
import org.onosproject.lisp.msg.protocols.LispMapRecord;
import org.onosproject.lisp.msg.protocols.LispMapRecord.MapRecordBuilder;
import org.onosproject.lisp.msg.protocols.LispMapRegister;
import org.onosproject.lisp.msg.protocols.LispMapRegister.RegisterBuilder;
import org.onosproject.lisp.msg.protocols.LispMapReplyAction;
import org.onosproject.lisp.msg.protocols.LispMessage;
import org.onosproject.lisp.msg.types.LispIpv4Address;
import org.osgi.service.component.ComponentContext;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static junit.framework.TestCase.fail;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;

/**
 * Unit tests for the LISP controller implementation class.
 */
public class LispControllerImplTest {

    private LispRouterId routerId1;
    private LispRouterId routerId2;
    private LispRouterId routerId3;
    private LispRouter router1;
    private LispRouter router2;
    private LispRouter router3;

    private LispControllerImpl controller;
    private LispRouterAgent agent;
    private TestRouterListener routerListener;
    private TestMessageListener messageListener;

    /**
     * Tests harness for a router routerListener.
     */
    static final class TestRouterListener implements LispRouterListener {

        final List<LispRouterId> removedIds = Lists.newArrayList();
        final List<LispRouterId> addedIds = Lists.newArrayList();
        final List<LispRouterId> changedIds = Lists.newArrayList();

        @Override
        public void routerAdded(LispRouterId routerId) {
            addedIds.add(routerId);
        }

        @Override
        public void routerRemoved(LispRouterId routerId) {
            removedIds.add(routerId);
        }

        @Override
        public void routerChanged(LispRouterId routerId) {
            changedIds.add(routerId);
        }
    }

    /**
     * Tests harness for a router messageListener.
     */
    static final class TestMessageListener implements LispMessageListener {

        final List<LispMessage> incomingMessages = Lists.newArrayList();
        final List<LispMessage> outgoingMessages = Lists.newArrayList();

        CountDownLatch incomingLatch = new CountDownLatch(1);
        CountDownLatch outgoingLatch = new CountDownLatch(1);

        @Override
        public void handleIncomingMessage(LispRouterId routerId, LispMessage msg) {
            synchronized (incomingMessages) {
                incomingMessages.add(msg);
                incomingLatch.countDown();
            }
        }

        @Override
        public void handleOutgoingMessage(LispRouterId routerId, LispMessage msg) {
            synchronized (outgoingMessages) {
                outgoingMessages.add(msg);
                outgoingLatch.countDown();
            }
        }

        public void waitUntilUpdateIsCalled() throws InterruptedException {
            incomingLatch.await();
            outgoingLatch.await();
        }
    }

    /**
     * Sets up routers to use as data, mocks and launches a controller instance.
     */
    @Before
    public void setUp() {
        try {
            router1 = new LispRouterAdapter();
            routerId1 = LispRouterId.routerId(new URI("lisp:10.1.1.1"));
            router2 = new LispRouterAdapter();
            routerId2 = LispRouterId.routerId(new URI("lisp:10.1.1.2"));
            router3 = new LispRouterAdapter();
            routerId3 = LispRouterId.routerId(new URI("lisp:10.1.1.3"));

        } catch (URISyntaxException e) {
            // this will never happen...
            fail();
        }

        controller = new LispControllerImpl();
        agent = controller.agent;

        routerListener = new TestRouterListener();
        controller.addRouterListener(routerListener);

        messageListener = new TestMessageListener();
        controller.addMessageListener(messageListener);

        controller.coreService = EasyMock.createMock(CoreService.class);

        ComponentConfigService mockConfigService =
                                EasyMock.createMock(ComponentConfigService.class);
        expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
        mockConfigService.registerProperties(controller.getClass());
        expectLastCall();
        mockConfigService.unregisterProperties(controller.getClass(), false);
        expectLastCall();
        expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
        controller.cfgService = mockConfigService;
        replay(mockConfigService);

        ComponentContext mockContext = EasyMock.createMock(ComponentContext.class);
        Dictionary<String, Object> properties = new Hashtable<>();
        properties.put("lispAuthKey", "onos");
        properties.put("lispAuthKeyId", 1);
        expect(mockContext.getProperties()).andReturn(properties);
        replay(mockContext);
        controller.activate(mockContext);
    }

    @After
    public void tearDown() {

        controller.removeRouterListener(routerListener);
        controller.removeMessageListener(messageListener);
        controller.deactivate();
    }

    /**
     * Tests adding and removing connected routers.
     */
    @Test
    public void testAddRemoveConnectedRouter() {

        // Test adding connected routers into agent
        boolean addRouter1 = agent.addConnectedRouter(routerId1, router1);
        assertThat(addRouter1, is(true));
        boolean addRouter2 = agent.addConnectedRouter(routerId2, router2);
        assertThat(addRouter2, is(true));
        boolean addRouter3 = agent.addConnectedRouter(routerId3, router3);
        assertThat(addRouter3, is(true));

        // Test the callback methods that contained in router listener is fired
        assertThat(routerListener.addedIds, hasSize(3));
        assertThat(routerListener.addedIds, hasItems(routerId1, routerId2, routerId3));

        // Test adding a router twice (duplicated router)
        // this should return false to indicate that there is already a router
        // has been added previously
        boolean addBadRouter1 = agent.addConnectedRouter(routerId1, router1);
        assertThat(addBadRouter1, is(false));

        // Also make sure that the duplicated router will never increase the counter
        assertThat(controller.connectedRouters.size(), is(3));

        // Test querying the router list
        Stream<LispRouter> queriedRouters = makeIntoStream(controller.getRouters());
        long routerCount = queriedRouters.count();
        assertThat(routerCount, is(3L));

        // Test querying the individual router
        LispRouter queriedRouter = controller.getRouter(routerId1);
        assertThat(queriedRouter, is(router1));

        // Test removing a router from connected router collection
        agent.removeConnectedRouter(routerId2);
        Stream<LispRouter> queriedRoutersAfterRemoval =
                            makeIntoStream(controller.getRouters());
        long routerCountAfterRemoval = queriedRoutersAfterRemoval.count();
        assertThat(routerCountAfterRemoval, is(2L));

        // Test the callback methods that contained in router listener is fired
        assertThat(routerListener.removedIds, hasSize(1));
        assertThat(routerListener.removedIds, hasItems(routerId2));

        // Test querying the removed switch
        LispRouter queriedRouterAfterRemoval = controller.getRouter(routerId2);
        assertThat(queriedRouterAfterRemoval, nullValue());
    }

    /**
     * Tests adding and removing LISP messages.
     */
    @Test
    public void testLispMessagePopulate() throws InterruptedException {

        RegisterBuilder registerBuilder = new DefaultRegisterBuilder();
        List<LispMapRecord> records = ImmutableList.of(getMapRecord(), getMapRecord());
        LispMapRegister register = registerBuilder
                                        .withIsProxyMapReply(true)
                                        .withIsWantMapNotify(false)
                                        .withKeyId((short) 1)
                                        .withAuthKey("onos")
                                        .withNonce(1L)
                                        .withMapRecords(records)
                                        .build();

        NotifyBuilder notifyBuilder = new DefaultNotifyBuilder();
        LispMapNotify notify = notifyBuilder
                                        .withKeyId((short) 1)
                                        .withAuthKey("onos")
                                        .withNonce(1L)
                                        .withMapRecords(records)
                                        .build();

        // Test the callback methods that contained in message listener is fired
        agent.processUpstreamMessage(routerId1, register);
        // Following line will be ignored
        agent.processUpstreamMessage(routerId1, notify);

        agent.processDownstreamMessage(routerId1, notify);
        // Following line will be ignored
        agent.processDownstreamMessage(routerId1, register);

        messageListener.waitUntilUpdateIsCalled();

        assertThat(messageListener.incomingMessages, hasSize(1));
        assertThat(messageListener.incomingMessages, hasItems(register));

        assertThat(messageListener.outgoingMessages, hasSize(1));
        assertThat(messageListener.outgoingMessages, hasItems(notify));
    }

    /**
     * Generates and returns a map record.
     *
     * @return a map record
     */
    private LispMapRecord getMapRecord() {
        MapRecordBuilder builder1 = new DefaultMapRecordBuilder();

        LispIpv4Address ipv4Locator1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.1"));

        return builder1
                .withRecordTtl(100)
                .withAuthoritative(true)
                .withMapVersionNumber((short) 1)
                .withMaskLength((byte) 0x01)
                .withAction(LispMapReplyAction.NativelyForward)
                .withEidPrefixAfi(ipv4Locator1)
                .build();
    }

    /**
     * Converts an Iterable of some type into a stream of that type.
     *
     * @param items Iterable of objects
     * @param <T> type of the items in the iterable
     * @return stream of objects of type T
     */
    private <T> Stream<T> makeIntoStream(Iterable<T> items) {
        return StreamSupport.stream(
                Spliterators.spliteratorUnknownSize(
                        items.iterator(), Spliterator.ORDERED), false);
    }
}
