/*
 * Copyright 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.dhcp.impl;

import com.google.common.collect.ImmutableSet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.DHCP;
import org.onlab.packet.DHCPOption;
import org.onlab.packet.DHCPPacketType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.UDP;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.dhcp.DhcpStore;
import org.onosproject.dhcp.IpAssignment;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.config.NetworkConfigRegistryAdapter;
import org.onosproject.net.host.HostDescription;
import org.onosproject.net.host.HostProvider;
import org.onosproject.net.host.HostProviderRegistry;
import org.onosproject.net.host.HostProviderService;
import org.onosproject.net.packet.DefaultInboundPacket;
import org.onosproject.net.packet.DefaultPacketContext;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketServiceAdapter;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.AbstractProviderService;
import org.onosproject.net.provider.ProviderId;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.onosproject.net.NetTestTools.connectPoint;

/**
 * Set of tests of the ONOS application component.
 */

public class DhcpManagerTest {

    private DhcpManager dhcpXManager;

    protected PacketProcessor packetProcessor;

    protected HostProviderService hostProviderService;

    private static final HostId CLIENT1_HOST = HostId.hostId(MacAddress.valueOf("1a:1a:1a:1a:1a:1a"));

    private static final String EXPECTED_IP = "10.2.0.2";

    private static final Ip4Address BROADCAST = Ip4Address.valueOf("255.255.255.255");

    private static final int TRANSACTION_ID = 1000;

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

    @Before
    public void setUp() {
        dhcpXManager = new DhcpManager();
        dhcpXManager.cfgService = new TestNetworkConfigRegistry();
        dhcpXManager.packetService = new TestPacketService();
        dhcpXManager.coreService = new TestCoreService();
        dhcpXManager.dhcpStore = new TestDhcpStore();
        hostProviderService = new TestHostProviderService(new TestHostProvider());
        dhcpXManager.hostProviderService = hostProviderService;
        dhcpXManager.hostProviderRegistry = new TestHostRegistry();
        dhcpXManager.activate();
    }

    @After
    public void tearDown() {
        dhcpXManager.deactivate();
    }

    /**
     * Tests the response to a DHCP Discover Packet.
     */
    @Test
    public void testDiscover() {
        Ethernet reply = constructDhcpPacket(DHCPPacketType.DHCPDISCOVER);
        sendPacket(reply);
    }

    /**
     * Tests the response to a DHCP Request Packet.
     */
    @Test
    public void testRequest() {
        Ethernet reply = constructDhcpPacket(DHCPPacketType.DHCPREQUEST);
        sendPacket(reply);
    }

    /**
     * Sends an Ethernet packet to the process method of the Packet Processor.
     * @param reply Ethernet packet
     */
    private void sendPacket(Ethernet reply) {
        final ByteBuffer byteBuffer = ByteBuffer.wrap(reply.serialize());
        InboundPacket inPacket = new DefaultInboundPacket(connectPoint("1", 1),
                reply,
                byteBuffer);

        PacketContext context = new TestPacketContext(127L, inPacket, null, false);
        packetProcessor.process(context);
    }

    /**
     * Constructs an Ethernet packet containing a DHCP Payload.
     * @param packetType DHCP Message Type
     * @return Ethernet packet
     */
    private Ethernet constructDhcpPacket(DHCPPacketType packetType) {

        // Ethernet Frame.
        Ethernet ethReply = new Ethernet();
        ethReply.setSourceMACAddress(CLIENT1_HOST.mac());
        ethReply.setDestinationMACAddress(MacAddress.BROADCAST);
        ethReply.setEtherType(Ethernet.TYPE_IPV4);
        ethReply.setVlanID((short) 2);

        // IP Packet
        IPv4 ipv4Reply = new IPv4();
        ipv4Reply.setSourceAddress(0);
        ipv4Reply.setDestinationAddress(BROADCAST.toInt());
        ipv4Reply.setTtl((byte) 127);

        // UDP Datagram.
        UDP udpReply = new UDP();
        udpReply.setSourcePort((byte) UDP.DHCP_CLIENT_PORT);
        udpReply.setDestinationPort((byte) UDP.DHCP_SERVER_PORT);

        // DHCP Payload.
        DHCP dhcpReply = new DHCP();
        dhcpReply.setOpCode(DHCP.OPCODE_REQUEST);

        dhcpReply.setYourIPAddress(0);
        dhcpReply.setServerIPAddress(0);

        dhcpReply.setTransactionId(TRANSACTION_ID);
        dhcpReply.setClientHardwareAddress(CLIENT1_HOST.mac().toBytes());
        dhcpReply.setHardwareType(DHCP.HWTYPE_ETHERNET);
        dhcpReply.setHardwareAddressLength((byte) 6);

        // DHCP Options.
        DHCPOption option = new DHCPOption();
        List<DHCPOption> optionList = new ArrayList<>();

        // DHCP Message Type.
        option.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
        option.setLength((byte) 1);
        byte[] optionData = {(byte) packetType.getValue()};
        option.setData(optionData);
        optionList.add(option);

        // DHCP Requested IP.
        option = new DHCPOption();
        option.setCode(DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue());
        option.setLength((byte) 4);
        optionData = Ip4Address.valueOf(EXPECTED_IP).toOctets();
        option.setData(optionData);
        optionList.add(option);

        // End Option.
        option = new DHCPOption();
        option.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
        option.setLength((byte) 1);
        optionList.add(option);

        dhcpReply.setOptions(optionList);

        udpReply.setPayload(dhcpReply);
        ipv4Reply.setPayload(udpReply);
        ethReply.setPayload(ipv4Reply);

        return ethReply;
    }

    /**
     * Validates the contents of the packet sent by the DHCP Manager.
     * @param packet Ethernet packet received
     */
    private void validatePacket(Ethernet packet) {
        DHCP dhcpPacket = (DHCP) packet.getPayload().getPayload().getPayload();
        assertEquals(MacAddress.valueOf(dhcpPacket.getClientHardwareAddress()), CLIENT1_HOST.mac());
        assertEquals(Ip4Address.valueOf(dhcpPacket.getYourIPAddress()), Ip4Address.valueOf(EXPECTED_IP));
        assertEquals(dhcpPacket.getTransactionId(), TRANSACTION_ID);
    }

    /**
     * Mocks the DHCPStore.
     */
    private final class TestDhcpStore implements DhcpStore {


        public void populateIPPoolfromRange(Ip4Address startIP, Ip4Address endIP) {
        }

        public Ip4Address suggestIP(HostId hostId, Ip4Address requestedIP) {
            return Ip4Address.valueOf(EXPECTED_IP);
        }

        public boolean assignIP(HostId hostId, Ip4Address ipAddr, int leaseTime, boolean fromOpenStack,
                                List<Ip4Address> addressList) {
            return true;
        }

        public void setDefaultTimeoutForPurge(int timeInSeconds) {
        }

        public Ip4Address releaseIP(HostId hostId) {
            return null;
        }

        public Map<HostId, IpAssignment> listAssignedMapping() {
            return listAllMapping();
        }

        public Map<HostId, IpAssignment> listAllMapping() {
            Map<HostId, IpAssignment> map = new HashMap<>();
            IpAssignment assignment = IpAssignment.builder()
                                        .ipAddress(Ip4Address.valueOf(EXPECTED_IP))
                                        .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned)
                                        .leasePeriod(300)
                                        .timestamp(new Date())
                                        .build();
            map.put(CLIENT1_HOST, assignment);
            return map;
        }

        public boolean assignStaticIP(MacAddress macID, Ip4Address ipAddr, boolean fromOpenStack,
                                      List<Ip4Address> addressList) {
            return true;
        }

        public boolean removeStaticIP(MacAddress macID) {
            return true;
        }

        public Iterable<Ip4Address> getAvailableIPs() {
            List<Ip4Address> ipList = new ArrayList<>();
            ipList.add(Ip4Address.valueOf(EXPECTED_IP));
            return ImmutableSet.copyOf(ipList);
        }
        public IpAssignment getIpAssignmentFromAllocationMap(HostId hostId) {
            return null;
        }
    }

    /**
     * Mocks the DefaultPacket context.
     */
    private final class TestPacketContext extends DefaultPacketContext {
        private TestPacketContext(long time, InboundPacket inPkt,
                                    OutboundPacket outPkt, boolean block) {
            super(time, inPkt, outPkt, block);
        }

        @Override
        public void send() {
            // We don't send anything out.
        }
    }

    /**
     * Keeps a reference to the PacketProcessor and verifies the OutboundPackets.
     */
    private class TestPacketService extends PacketServiceAdapter {

        @Override
        public void addProcessor(PacketProcessor processor, int priority) {
            packetProcessor = processor;
        }

        @Override
        public void emit(OutboundPacket packet) {
            try {
                Ethernet eth = Ethernet.deserializer().deserialize(packet.data().array(),
                        0, packet.data().array().length);
                validatePacket(eth);
            } catch (Exception e) {
                fail(e.getMessage());
            }
        }
    }

    /**
     * Mocks the CoreService.
     */
    private class TestCoreService extends CoreServiceAdapter {

    }

    /**
     * Mocks the NetworkConfigRegistry.
     */
    private class TestNetworkConfigRegistry extends NetworkConfigRegistryAdapter {

    }

    /**
     * Mocks the HostProviderService.
     */
    private class TestHostProviderService extends AbstractProviderService<HostProvider>
            implements HostProviderService {

        protected TestHostProviderService(HostProvider provider) {
            super(provider);
        }

        @Override
        public void hostDetected(HostId hostId, HostDescription hostDescription, boolean replaceIps) {

        }

        @Override
        public void hostVanished(HostId hostId) {
        }

        @Override
        public void removeIpFromHost(HostId hostId, IpAddress ipAddress) {

        }

    }

    /**
     * Mocks the HostProvider.
     */
    private static class TestHostProvider extends AbstractProvider
            implements HostProvider {

        protected TestHostProvider() {
            super(PID);
        }

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

        @Override
        public void triggerProbe(Host host) {
        }

    }

    /**
     * Mocks the HostProviderRegistry.
     */
    private class TestHostRegistry implements HostProviderRegistry {

        @Override
        public HostProviderService register(HostProvider provider) {
            return hostProviderService;
        }

        @Override
        public void unregister(HostProvider provider) {
        }

        @Override
        public Set<ProviderId> getProviders() {
            return null;
        }

    }

}
