/*
 * Copyright 2014-present Open Networking Foundation
 *
 * 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 com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv6;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.packet.ndp.NeighborSolicitation;
import org.onosproject.net.intf.Interface;
import org.onosproject.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.edge.EdgePortService;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
import org.onosproject.net.host.HostProvider;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketServiceAdapter;
import org.onosproject.net.provider.ProviderId;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class HostMonitorTest {

    private static final IpAddress TARGET_IPV4_ADDR =
            IpAddress.valueOf("10.0.0.1");
    private static final IpAddress SOURCE_IPV4_ADDR =
            IpAddress.valueOf("10.0.0.99");
    private static final InterfaceIpAddress IA1 =
            new InterfaceIpAddress(SOURCE_IPV4_ADDR, IpPrefix.valueOf("10.0.0.0/24"));
    private MacAddress sourceMac = MacAddress.valueOf(1L);

    private static final IpAddress TARGET_IPV6_ADDR =
            IpAddress.valueOf("1000::1");
    private static final IpAddress SOURCE_IPV6_ADDR =
            IpAddress.valueOf("1000::f");
    private static final InterfaceIpAddress IA2 =
            new InterfaceIpAddress(SOURCE_IPV6_ADDR, IpPrefix.valueOf("1000::/64"));
    private MacAddress sourceMac2 = MacAddress.valueOf(2L);

    private EdgePortService edgePortService;

    private HostMonitor hostMonitor;

    @Before
    public void setUp() {
        edgePortService = createMock(EdgePortService.class);
        expect(edgePortService.isEdgePoint(anyObject(ConnectPoint.class)))
                .andReturn(true).anyTimes();
        replay(edgePortService);
    }

    @After
    public void shutdown() {
        hostMonitor.shutdown();
    }

    @Test
    public void testMonitorIpv4HostExists() throws Exception {
        testMonitorHostExists(TARGET_IPV4_ADDR);
    }

    @Test
    public void testMonitorIpv6HostExists() throws Exception {
        testMonitorHostExists(TARGET_IPV6_ADDR);
    }

    private void testMonitorHostExists(IpAddress hostIp) throws Exception {
        ProviderId id = new ProviderId("fake://", "id");

        Host host = createMock(Host.class);
        expect(host.providerId()).andReturn(id).anyTimes();
        replay(host);

        HostManager hostManager = createMock(HostManager.class);
        expect(hostManager.getHostsByIp(hostIp))
                .andReturn(Collections.singleton(host))
                .anyTimes();
        replay(hostManager);

        HostProvider hostProvider = createMock(HostProvider.class);
        expect(hostProvider.id()).andReturn(id).anyTimes();
        hostProvider.triggerProbe(host);
        expectLastCall().times(2);
        replay(hostProvider);

        hostMonitor = new HostMonitor(null, hostManager, null, edgePortService);

        hostMonitor.registerHostProvider(hostProvider);
        hostMonitor.addMonitoringFor(hostIp);

        hostMonitor.run();

        verify(hostProvider);
    }

    @Test
    public void testMonitorIpv4HostDoesNotExist() throws Exception {

        HostManager hostManager = createMock(HostManager.class);

        DeviceId devId = DeviceId.deviceId("fake");

        Device device = createMock(Device.class);
        expect(device.id()).andReturn(devId).anyTimes();
        replay(device);

        PortNumber portNum = PortNumber.portNumber(1L);

        Port port = createMock(Port.class);
        expect(port.number()).andReturn(portNum).anyTimes();
        replay(port);

        TestDeviceService deviceService = new TestDeviceService();
        deviceService.addDevice(device, Collections.singleton(port));

        ConnectPoint cp = new ConnectPoint(devId, portNum);

        expect(hostManager.getHostsByIp(TARGET_IPV4_ADDR))
                .andReturn(Collections.emptySet()).anyTimes();
        replay(hostManager);

        InterfaceService interfaceService = createMock(InterfaceService.class);
        expect(interfaceService.getMatchingInterfaces(TARGET_IPV4_ADDR))
                .andReturn(Collections.singleton(new Interface(Interface.NO_INTERFACE_NAME,
                        cp, Collections.singletonList(IA1), sourceMac, VlanId.NONE)))
                .anyTimes();
        replay(interfaceService);

        TestPacketService packetService = new TestPacketService();


        // Run the test
        hostMonitor = new HostMonitor(packetService, hostManager, interfaceService, edgePortService);

        hostMonitor.addMonitoringFor(TARGET_IPV4_ADDR);
        hostMonitor.run();


        // Check that a packet was sent to our PacketService and that it has
        // the properties we expect
        assertEquals(2, packetService.packets.size());
        OutboundPacket packet = packetService.packets.get(0);

        // Check the output port is correct
        assertEquals(1, packet.treatment().immediate().size());
        Instruction instruction = packet.treatment().immediate().get(0);
        assertTrue(instruction instanceof OutputInstruction);
        OutputInstruction oi = (OutputInstruction) instruction;
        assertEquals(portNum, oi.port());

        // Check the output packet is correct (well the important bits anyway)
        final byte[] pktData = new byte[packet.data().remaining()];
        packet.data().get(pktData);
        Ethernet eth = Ethernet.deserializer().deserialize(pktData, 0, pktData.length);
        assertEquals(Ethernet.VLAN_UNTAGGED, eth.getVlanID());
        ARP arp = (ARP) eth.getPayload();
        assertArrayEquals(SOURCE_IPV4_ADDR.toOctets(),
                          arp.getSenderProtocolAddress());
        assertArrayEquals(sourceMac.toBytes(),
                          arp.getSenderHardwareAddress());
        assertArrayEquals(TARGET_IPV4_ADDR.toOctets(),
                          arp.getTargetProtocolAddress());
    }

    @Test
    public void testMonitorIpv6HostDoesNotExist() throws Exception {

        HostManager hostManager = createMock(HostManager.class);

        DeviceId devId = DeviceId.deviceId("fake");

        Device device = createMock(Device.class);
        expect(device.id()).andReturn(devId).anyTimes();
        replay(device);

        PortNumber portNum = PortNumber.portNumber(2L);

        Port port = createMock(Port.class);
        expect(port.number()).andReturn(portNum).anyTimes();
        replay(port);

        TestDeviceService deviceService = new TestDeviceService();
        deviceService.addDevice(device, Collections.singleton(port));

        ConnectPoint cp = new ConnectPoint(devId, portNum);

        expect(hostManager.getHostsByIp(TARGET_IPV6_ADDR))
                .andReturn(Collections.emptySet()).anyTimes();
        replay(hostManager);

        InterfaceService interfaceService = createMock(InterfaceService.class);
        expect(interfaceService.getMatchingInterfaces(TARGET_IPV6_ADDR))
                .andReturn(Collections.singleton(new Interface(Interface.NO_INTERFACE_NAME, cp,
                        Collections.singletonList(IA2), sourceMac2, VlanId.NONE)))
                .anyTimes();
        replay(interfaceService);

        TestPacketService packetService = new TestPacketService();


        // Run the test
        hostMonitor = new HostMonitor(packetService, hostManager, interfaceService, edgePortService);

        hostMonitor.addMonitoringFor(TARGET_IPV6_ADDR);
        hostMonitor.run();


        // Check that a packet was sent to our PacketService and that it has
        // the properties we expect
        assertEquals(2, packetService.packets.size());
        OutboundPacket packet = packetService.packets.get(0);

        // Check the output port is correct
        assertEquals(1, packet.treatment().immediate().size());
        Instruction instruction = packet.treatment().immediate().get(0);
        assertTrue(instruction instanceof OutputInstruction);
        OutputInstruction oi = (OutputInstruction) instruction;
        assertEquals(portNum, oi.port());

        // Check the output packet is correct (well the important bits anyway)
        final byte[] pktData = new byte[packet.data().remaining()];
        packet.data().get(pktData);
        Ethernet eth = Ethernet.deserializer().deserialize(pktData, 0, pktData.length);
        assertEquals(Ethernet.VLAN_UNTAGGED, eth.getVlanID());
        IPv6 ipv6 = (IPv6) eth.getPayload();
        assertArrayEquals(SOURCE_IPV6_ADDR.toOctets(), ipv6.getSourceAddress());

        NeighborSolicitation ns =
                (NeighborSolicitation) ipv6.getPayload().getPayload();
        assertArrayEquals(sourceMac2.toBytes(), ns.getOptions().get(0).data());

        assertArrayEquals(TARGET_IPV6_ADDR.toOctets(), ns.getTargetAddress());
    }

    @Test
    public void testMonitorIpv4HostDoesNotExistWithVlan() throws Exception {

        HostManager hostManager = createMock(HostManager.class);

        DeviceId devId = DeviceId.deviceId("fake");
        short vlan = 5;

        Device device = createMock(Device.class);
        expect(device.id()).andReturn(devId).anyTimes();
        replay(device);

        PortNumber portNum = PortNumber.portNumber(1L);

        Port port = createMock(Port.class);
        expect(port.number()).andReturn(portNum).anyTimes();
        replay(port);

        TestDeviceService deviceService = new TestDeviceService();
        deviceService.addDevice(device, Collections.singleton(port));

        ConnectPoint cp = new ConnectPoint(devId, portNum);

        expect(hostManager.getHostsByIp(TARGET_IPV4_ADDR))
                .andReturn(Collections.emptySet()).anyTimes();
        replay(hostManager);

        InterfaceService interfaceService = createMock(InterfaceService.class);
        expect(interfaceService.getMatchingInterfaces(TARGET_IPV4_ADDR))
                .andReturn(Collections.singleton(new Interface(Interface.NO_INTERFACE_NAME, cp,
                        Collections.singletonList(IA1), sourceMac, VlanId.vlanId(vlan))))
                .anyTimes();
        replay(interfaceService);

        TestPacketService packetService = new TestPacketService();


        // Run the test
        hostMonitor = new HostMonitor(packetService, hostManager, interfaceService, edgePortService);

        hostMonitor.addMonitoringFor(TARGET_IPV4_ADDR);
        hostMonitor.run();


        // Check that a packet was sent to our PacketService and that it has
        // the properties we expect
        assertEquals(2, packetService.packets.size());
        OutboundPacket packet = packetService.packets.get(0);

        // Check the output port is correct
        assertEquals(1, packet.treatment().immediate().size());
        Instruction instruction = packet.treatment().immediate().get(0);
        assertTrue(instruction instanceof OutputInstruction);
        OutputInstruction oi = (OutputInstruction) instruction;
        assertEquals(portNum, oi.port());

        // Check the output packet is correct (well the important bits anyway)
        final byte[] pktData = new byte[packet.data().remaining()];
        packet.data().get(pktData);
        Ethernet eth = Ethernet.deserializer().deserialize(pktData, 0, pktData.length);
        assertEquals(vlan, eth.getVlanID());
        ARP arp = (ARP) eth.getPayload();
        assertArrayEquals(SOURCE_IPV4_ADDR.toOctets(),
                          arp.getSenderProtocolAddress());
        assertArrayEquals(sourceMac.toBytes(),
                          arp.getSenderHardwareAddress());
        assertArrayEquals(TARGET_IPV4_ADDR.toOctets(),
                          arp.getTargetProtocolAddress());
    }

    @Test
    public void testMonitorIpv6HostDoesNotExistWithVlan() throws Exception {

        HostManager hostManager = createMock(HostManager.class);

        DeviceId devId = DeviceId.deviceId("fake");
        short vlan = 5;

        Device device = createMock(Device.class);
        expect(device.id()).andReturn(devId).anyTimes();
        replay(device);

        PortNumber portNum = PortNumber.portNumber(1L);

        Port port = createMock(Port.class);
        expect(port.number()).andReturn(portNum).anyTimes();
        replay(port);

        TestDeviceService deviceService = new TestDeviceService();
        deviceService.addDevice(device, Collections.singleton(port));

        ConnectPoint cp = new ConnectPoint(devId, portNum);

        expect(hostManager.getHostsByIp(TARGET_IPV6_ADDR))
                .andReturn(Collections.emptySet()).anyTimes();
        replay(hostManager);

        InterfaceService interfaceService = createMock(InterfaceService.class);
        expect(interfaceService.getMatchingInterfaces(TARGET_IPV6_ADDR))
                .andReturn(Collections.singleton(new Interface(Interface.NO_INTERFACE_NAME, cp,
                        Collections.singletonList(IA2), sourceMac2, VlanId.vlanId(vlan))))
                .anyTimes();
        replay(interfaceService);

        TestPacketService packetService = new TestPacketService();


        // Run the test
        hostMonitor = new HostMonitor(packetService, hostManager, interfaceService, edgePortService);

        hostMonitor.addMonitoringFor(TARGET_IPV6_ADDR);
        hostMonitor.run();


        // Check that a packet was sent to our PacketService and that it has
        // the properties we expect
        assertEquals(2, packetService.packets.size());
        OutboundPacket packet = packetService.packets.get(0);

        // Check the output port is correct
        assertEquals(1, packet.treatment().immediate().size());
        Instruction instruction = packet.treatment().immediate().get(0);
        assertTrue(instruction instanceof OutputInstruction);
        OutputInstruction oi = (OutputInstruction) instruction;
        assertEquals(portNum, oi.port());

        // Check the output packet is correct (well the important bits anyway)
        final byte[] pktData = new byte[packet.data().remaining()];
        packet.data().get(pktData);
        Ethernet eth = Ethernet.deserializer().deserialize(pktData, 0, pktData.length);
        assertEquals(vlan, eth.getVlanID());
        IPv6 ipv6 = (IPv6) eth.getPayload();
        assertArrayEquals(SOURCE_IPV6_ADDR.toOctets(), ipv6.getSourceAddress());

        NeighborSolicitation ns =
                (NeighborSolicitation) ipv6.getPayload().getPayload();
        assertArrayEquals(sourceMac2.toBytes(), ns.getOptions().get(0).data());

        assertArrayEquals(TARGET_IPV6_ADDR.toOctets(), ns.getTargetAddress());
    }

    class TestPacketService extends PacketServiceAdapter {

        List<OutboundPacket> packets = new ArrayList<>();

        @Override
        public void emit(OutboundPacket packet) {
            packets.add(packet);
        }
    }

    class TestDeviceService extends DeviceServiceAdapter {

        List<Device> devices = Lists.newArrayList();
        Multimap<DeviceId, Port> devicePorts = HashMultimap.create();

        void addDevice(Device device, Set<Port> ports) {
            devices.add(device);
            for (Port p : ports) {
                devicePorts.put(device.id(), p);
            }
        }

        @Override
        public Iterable<Device> getDevices() {
            return devices;
        }

        @Override
        public List<Port> getPorts(DeviceId deviceId) {
            List<Port> ports = Lists.newArrayList();
            for (Port p : devicePorts.get(deviceId)) {
                ports.add(p);
            }
            return ports;
        }
    }
}
