/*
 * Copyright 2014-2015 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.net.host.impl;

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.assertTrue;
import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
import static org.onosproject.net.host.HostEvent.Type.HOST_MOVED;
import static org.onosproject.net.host.HostEvent.Type.HOST_REMOVED;
import static org.onosproject.net.host.HostEvent.Type.HOST_UPDATED;

import java.util.List;
import java.util.Set;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.event.Event;
import org.onosproject.event.impl.TestEventDispatcher;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.PortNumber;
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostDescription;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostProvider;
import org.onosproject.net.host.HostProviderRegistry;
import org.onosproject.net.host.HostProviderService;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.host.PortAddresses;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.store.trivial.impl.SimpleHostStore;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

/**
 * Test codifying the host service & host provider service contracts.
 */
public class HostManagerTest {

    private static final ProviderId PID = new ProviderId("of", "foo");

    private static final VlanId VLAN1 = VlanId.vlanId((short) 1);
    private static final VlanId VLAN2 = VlanId.vlanId((short) 2);
    private static final MacAddress MAC1 = MacAddress.valueOf("00:00:11:00:00:01");
    private static final MacAddress MAC2 = MacAddress.valueOf("00:00:22:00:00:02");
    private static final MacAddress MAC3 = MacAddress.valueOf("00:00:33:00:00:03");
    private static final MacAddress MAC4 = MacAddress.valueOf("00:00:44:00:00:04");
    private static final HostId HID1 = HostId.hostId(MAC1, VLAN1);
    private static final HostId HID2 = HostId.hostId(MAC2, VLAN1);
    private static final HostId HID3 = HostId.hostId(MAC3, VLAN1);
    private static final HostId HID4 = HostId.hostId(MAC4, VLAN1);

    private static final IpAddress IP1 = IpAddress.valueOf("10.0.0.1");
    private static final IpAddress IP2 = IpAddress.valueOf("10.0.0.2");
    private static final IpAddress IP3 = IpAddress.valueOf("2001::1");
    private static final IpAddress IP4 = IpAddress.valueOf("2001::2");

    private static final DeviceId DID1 = DeviceId.deviceId("of:001");
    private static final DeviceId DID2 = DeviceId.deviceId("of:002");
    private static final PortNumber P1 = PortNumber.portNumber(100);
    private static final PortNumber P2 = PortNumber.portNumber(200);
    private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L);
    private static final HostLocation LOC2 = new HostLocation(DID1, P2, 123L);
    private static final ConnectPoint CP1 = new ConnectPoint(DID1, P1);
    private static final ConnectPoint CP2 = new ConnectPoint(DID2, P2);

    private static final InterfaceIpAddress IA1 =
        new InterfaceIpAddress(IpAddress.valueOf("10.1.1.1"),
                               IpPrefix.valueOf("10.1.1.0/24"));
    private static final InterfaceIpAddress IA2 =
        new InterfaceIpAddress(IpAddress.valueOf("10.2.2.2"),
                               IpPrefix.valueOf("10.2.0.0/16"));
    private static final InterfaceIpAddress IA3 =
        new InterfaceIpAddress(IpAddress.valueOf("10.3.3.3"),
                               IpPrefix.valueOf("10.3.3.0/24"));
    private static final InterfaceIpAddress IA4 =
        new InterfaceIpAddress(IpAddress.valueOf("2001:100::1"),
                               IpPrefix.valueOf("2001:100::/56"));
    private static final InterfaceIpAddress IA5 =
        new InterfaceIpAddress(IpAddress.valueOf("2001:200::1"),
                               IpPrefix.valueOf("2001:200::/48"));
    private static final InterfaceIpAddress IA6 =
        new InterfaceIpAddress(IpAddress.valueOf("2001:300::1"),
                               IpPrefix.valueOf("2001:300::/56"));

    private HostManager mgr;

    protected TestListener listener = new TestListener();
    protected HostProviderRegistry registry;
    protected TestHostProvider provider;
    protected HostProviderService providerService;

    @Before
    public void setUp() {
        mgr = new HostManager();
        mgr.store = new SimpleHostStore();
        mgr.eventDispatcher = new TestEventDispatcher();
        registry = mgr;
        mgr.activate();

        mgr.addListener(listener);

        provider = new TestHostProvider();
        providerService = registry.register(provider);
        assertTrue("provider should be registered",
                   registry.getProviders().contains(provider.id()));
    }

    @After
    public void tearDown() {
        registry.unregister(provider);
        assertFalse("provider should not be registered",
                    registry.getProviders().contains(provider.id()));

        mgr.removeListener(listener);
        mgr.deactivate();
        mgr.eventDispatcher = null;
    }

    private void detect(HostId hid, MacAddress mac, VlanId vlan,
                        HostLocation loc, IpAddress ip) {
        HostDescription descr = new DefaultHostDescription(mac, vlan, loc, ip);
        providerService.hostDetected(hid, descr);
        assertNotNull("host should be found", mgr.getHost(hid));
    }

    private void validateEvents(Enum... types) {
        int i = 0;
        assertEquals("wrong events received", types.length, listener.events.size());
        for (Event event : listener.events) {
            assertEquals("incorrect event type", types[i], event.type());
            i++;
        }
        listener.events.clear();
    }

    @Test
    public void hostDetected() {
        assertNull("host shouldn't be found", mgr.getHost(HID1));

        // host addition
        detect(HID1, MAC1, VLAN1, LOC1, IP1);
        assertEquals("exactly one should be found", 1, mgr.getHostCount());
        detect(HID2, MAC2, VLAN2, LOC2, IP1);
        assertEquals("two hosts should be found", 2, mgr.getHostCount());
        validateEvents(HOST_ADDED, HOST_ADDED);

        // host motion
        detect(HID1, MAC1, VLAN1, LOC2, IP1);
        validateEvents(HOST_MOVED);
        assertEquals("only two hosts should be found", 2, mgr.getHostCount());

        // host update
        detect(HID1, MAC1, VLAN1, LOC2, IP2);
        validateEvents(HOST_UPDATED);
        assertEquals("only two hosts should be found", 2, mgr.getHostCount());
    }

    @Test
    public void hostDetectedIPv6() {
        assertNull("host shouldn't be found", mgr.getHost(HID3));

        // host addition
        detect(HID3, MAC3, VLAN1, LOC1, IP3);
        assertEquals("exactly one should be found", 1, mgr.getHostCount());
        detect(HID4, MAC4, VLAN2, LOC2, IP3);
        assertEquals("two hosts should be found", 2, mgr.getHostCount());
        validateEvents(HOST_ADDED, HOST_ADDED);

        // host motion
        detect(HID3, MAC3, VLAN1, LOC2, IP3);
        validateEvents(HOST_MOVED);
        assertEquals("only two hosts should be found", 2, mgr.getHostCount());

        // host update
        detect(HID3, MAC3, VLAN1, LOC2, IP4);
        validateEvents(HOST_UPDATED);
        assertEquals("only two hosts should be found", 2, mgr.getHostCount());
    }

    @Test
    public void hostVanished() {
        detect(HID1, MAC1, VLAN1, LOC1, IP1);
        providerService.hostVanished(HID1);
        validateEvents(HOST_ADDED, HOST_REMOVED);

        assertNull("host should have been removed", mgr.getHost(HID1));
    }

    @Test
    public void hostVanishedIPv6() {
        detect(HID3, MAC3, VLAN1, LOC1, IP3);
        providerService.hostVanished(HID3);
        validateEvents(HOST_ADDED, HOST_REMOVED);

        assertNull("host should have been removed", mgr.getHost(HID3));
    }

    private void validateHosts(
            String msg, Iterable<Host> hosts, HostId... ids) {
        Set<HostId> hids = Sets.newHashSet(ids);
        for (Host h : hosts) {
            assertTrue(msg, hids.remove(h.id()));
        }
        assertTrue("expected hosts not fetched from store", hids.isEmpty());
    }

    @Test
    public void getHosts() {
        detect(HID1, MAC1, VLAN1, LOC1, IP1);
        detect(HID2, MAC2, VLAN1, LOC2, IP2);

        validateHosts("host not properly stored", mgr.getHosts(), HID1, HID2);
        validateHosts("can't get hosts by VLAN", mgr.getHostsByVlan(VLAN1), HID1, HID2);
        validateHosts("can't get hosts by MAC", mgr.getHostsByMac(MAC1), HID1);
        validateHosts("can't get hosts by IP", mgr.getHostsByIp(IP1), HID1);
        validateHosts("can't get hosts by location", mgr.getConnectedHosts(LOC1), HID1);
        assertTrue("incorrect host location", mgr.getConnectedHosts(DID2).isEmpty());
    }

    @Test
    public void getHostsIPv6() {
        detect(HID3, MAC3, VLAN1, LOC1, IP3);
        detect(HID4, MAC4, VLAN1, LOC2, IP4);

        validateHosts("host not properly stored", mgr.getHosts(), HID3, HID4);
        validateHosts("can't get hosts by VLAN", mgr.getHostsByVlan(VLAN1), HID3, HID4);
        validateHosts("can't get hosts by MAC", mgr.getHostsByMac(MAC3), HID3);
        validateHosts("can't get hosts by IP", mgr.getHostsByIp(IP3), HID3);
        validateHosts("can't get hosts by location", mgr.getConnectedHosts(LOC1), HID3);
        assertTrue("incorrect host location", mgr.getConnectedHosts(DID2).isEmpty());
    }

    private static class TestHostProvider extends AbstractProvider
            implements HostProvider {

        protected TestHostProvider() {
            super(PID);
        }

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

        @Override
        public void triggerProbe(Host host) {
        }

    }

    private static class TestListener implements HostListener {

        protected List<HostEvent> events = Lists.newArrayList();

        @Override
        public void event(HostEvent event) {
            events.add(event);
        }

    }

    @Test
    public void bindAddressesToPort() {
        PortAddresses add1 =
            new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1, VlanId.NONE);

        mgr.bindAddressesToPort(add1);
        Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertEquals(1, storedAddresses.size());
        assertTrue(storedAddresses.contains(add1));

        // Add some more addresses and check that they're added correctly
        PortAddresses add2 =
            new PortAddresses(CP1, Sets.newHashSet(IA3),  null,
                              VlanId.vlanId((short) 2));

        mgr.bindAddressesToPort(add2);
        storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertEquals(2, storedAddresses.size());
        assertTrue(storedAddresses.contains(add1));
        assertTrue(storedAddresses.contains(add2));

        PortAddresses add3 = new PortAddresses(CP1, null, MAC2, VlanId.NONE);

        mgr.bindAddressesToPort(add3);
        storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertEquals(3, storedAddresses.size());
        assertTrue(storedAddresses.contains(add1));
        assertTrue(storedAddresses.contains(add2));
        assertTrue(storedAddresses.contains(add3));
    }

    @Test
    public void bindAddressesToPortIPv6() {
        PortAddresses add1 =
                new PortAddresses(CP1, Sets.newHashSet(IA4, IA5), MAC3, VlanId.NONE);

        mgr.bindAddressesToPort(add1);
        Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertEquals(1, storedAddresses.size());
        assertTrue(storedAddresses.contains(add1));

        // Add some more addresses and check that they're added correctly
        PortAddresses add2 =
                new PortAddresses(CP1, Sets.newHashSet(IA6),  null,
                        VlanId.vlanId((short) 2));

        mgr.bindAddressesToPort(add2);
        storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertEquals(2, storedAddresses.size());
        assertTrue(storedAddresses.contains(add1));
        assertTrue(storedAddresses.contains(add2));

        PortAddresses add3 = new PortAddresses(CP1, null, MAC4, VlanId.NONE);

        mgr.bindAddressesToPort(add3);
        storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertEquals(3, storedAddresses.size());
        assertTrue(storedAddresses.contains(add1));
        assertTrue(storedAddresses.contains(add2));
        assertTrue(storedAddresses.contains(add3));
    }

    @Test
    public void unbindAddressesFromPort() {
        PortAddresses add1 =
            new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1, VlanId.NONE);

        mgr.bindAddressesToPort(add1);
        Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertEquals(1, storedAddresses.size());
        assertTrue(storedAddresses.contains(add1));

        PortAddresses rem1 =
            new PortAddresses(CP1, Sets.newHashSet(IA1), null, VlanId.NONE);

        mgr.unbindAddressesFromPort(rem1);
        storedAddresses = mgr.getAddressBindingsForPort(CP1);

        // It shouldn't have been removed because it didn't match the originally
        // submitted address object
        assertEquals(1, storedAddresses.size());
        assertTrue(storedAddresses.contains(add1));

        mgr.unbindAddressesFromPort(add1);
        storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertTrue(storedAddresses.isEmpty());
    }

    @Test
    public void unbindAddressesFromPortIPv6() {
        PortAddresses add1 =
                new PortAddresses(CP1, Sets.newHashSet(IA4, IA5), MAC3, VlanId.NONE);

        mgr.bindAddressesToPort(add1);
        Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertEquals(1, storedAddresses.size());
        assertTrue(storedAddresses.contains(add1));

        PortAddresses rem1 =
                new PortAddresses(CP1, Sets.newHashSet(IA4), null, VlanId.NONE);

        mgr.unbindAddressesFromPort(rem1);
        storedAddresses = mgr.getAddressBindingsForPort(CP1);

        // It shouldn't have been removed because it didn't match the originally
        // submitted address object
        assertEquals(1, storedAddresses.size());
        assertTrue(storedAddresses.contains(add1));

        mgr.unbindAddressesFromPort(add1);
        storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertTrue(storedAddresses.isEmpty());
    }

    @Test
    public void clearAddresses() {
        PortAddresses add1 =
            new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1, VlanId.NONE);

        mgr.bindAddressesToPort(add1);
        Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertEquals(1, storedAddresses.size());
        assertTrue(storedAddresses.contains(add1));

        mgr.clearAddresses(CP1);
        storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertTrue(storedAddresses.isEmpty());
    }

    @Test
    public void clearAddressesIPv6() {
        PortAddresses add1 =
                new PortAddresses(CP1, Sets.newHashSet(IA4, IA5), MAC3, VlanId.NONE);

        mgr.bindAddressesToPort(add1);
        Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertEquals(1, storedAddresses.size());
        assertTrue(storedAddresses.contains(add1));

        mgr.clearAddresses(CP1);
        storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertTrue(storedAddresses.isEmpty());
    }

    @Test
    public void getAddressBindingsForPort() {
        PortAddresses add1 =
            new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1, VlanId.NONE);

        mgr.bindAddressesToPort(add1);
        Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertEquals(1, storedAddresses.size());
        assertTrue(storedAddresses.contains(add1));
    }

    @Test
    public void getAddressBindingsForPortIPv6() {
        PortAddresses add1 =
                new PortAddresses(CP1, Sets.newHashSet(IA4, IA5), MAC3, VlanId.NONE);

        mgr.bindAddressesToPort(add1);
        Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1);

        assertEquals(1, storedAddresses.size());
        assertTrue(storedAddresses.contains(add1));
    }

    @Test
    public void getAddressBindings() {
        Set<PortAddresses> storedAddresses = mgr.getAddressBindings();

        assertTrue(storedAddresses.isEmpty());

        PortAddresses add1 =
            new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1, VlanId.NONE);

        mgr.bindAddressesToPort(add1);

        storedAddresses = mgr.getAddressBindings();

        assertTrue(storedAddresses.size() == 1);

        PortAddresses add2 =
            new PortAddresses(CP2, Sets.newHashSet(IA3), MAC2, VlanId.NONE);

        mgr.bindAddressesToPort(add2);

        storedAddresses = mgr.getAddressBindings();

        assertTrue(storedAddresses.size() == 2);
        assertTrue(storedAddresses.equals(Sets.newHashSet(add1, add2)));
    }

    @Test
    public void getAddressBindingsIPv6() {
        Set<PortAddresses> storedAddresses = mgr.getAddressBindings();

        assertTrue(storedAddresses.isEmpty());

        PortAddresses add1 =
                new PortAddresses(CP1, Sets.newHashSet(IA4, IA5), MAC3, VlanId.NONE);

        mgr.bindAddressesToPort(add1);

        storedAddresses = mgr.getAddressBindings();

        assertTrue(storedAddresses.size() == 1);

        PortAddresses add2 =
                new PortAddresses(CP2, Sets.newHashSet(IA5), MAC4, VlanId.NONE);

        mgr.bindAddressesToPort(add2);

        storedAddresses = mgr.getAddressBindings();

        assertTrue(storedAddresses.size() == 2);
        assertTrue(storedAddresses.equals(Sets.newHashSet(add1, add2)));
    }
}
