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

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.DHCP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.UDP;
import org.onlab.packet.dhcp.DhcpOption;
import org.onosproject.cfg.ComponentConfigAdapter;
import org.onosproject.cluster.ClusterServiceAdapter;
import org.onosproject.cluster.LeadershipServiceAdapter;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.HostId;
import org.onosproject.net.PortNumber;
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.openstacknetworking.api.InstancePort;
import org.openstack4j.model.network.AllowedAddressPair;
import org.openstack4j.model.network.HostRoute;
import org.openstack4j.model.network.IP;
import org.openstack4j.model.network.IPVersionType;
import org.openstack4j.model.network.Ipv6AddressMode;
import org.openstack4j.model.network.Ipv6RaMode;
import org.openstack4j.model.network.Network;
import org.openstack4j.model.network.NetworkType;
import org.openstack4j.model.network.Pool;
import org.openstack4j.model.network.Port;
import org.openstack4j.model.network.State;
import org.openstack4j.model.network.Subnet;
import org.openstack4j.model.network.builder.NetworkBuilder;
import org.openstack4j.model.network.builder.PortBuilder;
import org.openstack4j.model.network.builder.SubnetBuilder;
import org.openstack4j.openstack.networking.domain.NeutronHostRoute;
import org.openstack4j.openstack.networking.domain.NeutronIP;

import java.nio.ByteBuffer;
import java.util.ArrayList;
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.onlab.packet.DHCP.DHCPOptionCode.OptionCode_Classless_Static_Route;
import static org.onlab.packet.DHCP.DHCPOptionCode.OptionCode_DomainServer;
import static org.onlab.packet.DHCP.DHCPOptionCode.OptionCode_END;
import static org.onlab.packet.DHCP.DHCPOptionCode.OptionCode_MessageType;
import static org.onlab.packet.DHCP.DHCPOptionCode.OptionCode_RequestedIP;
import static org.onlab.packet.DHCP.DHCPOptionCode.OptionCode_RouterAddress;
import static org.onosproject.net.NetTestTools.connectPoint;

/**
 * Unit tests for Openstack switching DHCP handler.
 */
public class OpenstackSwitchingDhcpHandlerTest {

    private OpenstackSwitchingDhcpHandler dhcpHandler;

    protected PacketProcessor packetProcessor;

    private static final byte DHCP_OPTION_MTU = (byte) 26;

    private static final short MTU = 1450;
    private static final HostId CLIENT_HOST =
                         HostId.hostId(MacAddress.valueOf("1a:1a:1a:1a:1a:1a"));
    private static final String EXPECTED_IP = "10.2.0.2";
    private static final String EXPECTED_CIDR = "10.2.0.0/24";
    private static final String EXPECTED_GATEWAY = "10.2.0.1";
    private static final Ip4Address BROADCAST =
                         Ip4Address.valueOf("255.255.255.255");
    private static final int TRANSACTION_ID = 1986;
    private static final Ip4Address DEFAULT_PRIMARY_DNS = Ip4Address.valueOf("8.8.8.8");
    private static final Ip4Address DEFAULT_SECONDARY_DNS = Ip4Address.valueOf("8.8.4.4");
    private static final String HOST_ROUTE_1_DESTINATION = "0.0.0.0/0";
    private static final String HOST_ROUTE_1_NEXTHOP = "10.2.0.1";
    private static final String HOST_ROUTE_2_DESTINATION = "10.0.0.0/8";
    private static final String HOST_ROUTE_2_NEXTHOP = "10.2.0.1";
    private static final String HOST_ROUTE_3_DESTINATION = "10.0.0.0/16";
    private static final String HOST_ROUTE_3_NEXTHOP = "10.2.0.1";
    private static final String HOST_ROUTE_4_DESTINATION = "10.0.0.0/24";
    private static final String HOST_ROUTE_4_NEXTHOP = "10.2.0.1";
    private static final HostRoute HOST_ROUTE_1 = new NeutronHostRoute(HOST_ROUTE_1_DESTINATION, HOST_ROUTE_1_NEXTHOP);
    private static final HostRoute HOST_ROUTE_2 = new NeutronHostRoute(HOST_ROUTE_2_DESTINATION, HOST_ROUTE_2_NEXTHOP);
    private static final HostRoute HOST_ROUTE_3 = new NeutronHostRoute(HOST_ROUTE_3_DESTINATION, HOST_ROUTE_3_NEXTHOP);
    private static final HostRoute HOST_ROUTE_4 = new NeutronHostRoute(HOST_ROUTE_4_DESTINATION, HOST_ROUTE_4_NEXTHOP);
    private static final int HOST_ROUTES_SIZE = 26;

    private static final String IP_SUBNET_ID = "1";

    private DHCP.MsgType testMsgType;

    @Before
    public void setUp() {
        dhcpHandler = new OpenstackSwitchingDhcpHandler();
        dhcpHandler.coreService = new TestCoreService();
        dhcpHandler.configService = new TestConfigService();
        dhcpHandler.packetService = new TestPacketService();
        dhcpHandler.instancePortService = new TestInstancePortService();
        dhcpHandler.osNetworkService = new TestOpenstackNetworkService();
        dhcpHandler.osNodeService = new TestOpenstackNodeService();
        dhcpHandler.osFlowRuleService = new TestOpenstackFlowRuleService();
        dhcpHandler.clusterService = new TestClusterService();
        dhcpHandler.leadershipService = new TestLeadershipService();
        dhcpHandler.activate();
    }

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

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

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

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

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

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

        if (testMsgType == DHCP.MsgType.DHCPDISCOVER) {
            assertEquals(dhcpPacket.getPacketType(), DHCP.MsgType.DHCPOFFER);
        }

        if (testMsgType == DHCP.MsgType.DHCPREQUEST) {
            assertEquals(dhcpPacket.getPacketType(), DHCP.MsgType.DHCPACK);
        }
    }

    /**
     * Constructs an Ethernet packet containing a DHCP payload.
     *
     * @param msgType DHCP message type
     * @return Ethernet packet
     */
    private Ethernet constructDhcpPacket(DHCP.MsgType msgType) {

        // Ethernet frame
        Ethernet ethFrame = new Ethernet();
        ethFrame.setSourceMACAddress(CLIENT_HOST.mac());
        ethFrame.setDestinationMACAddress(MacAddress.BROADCAST);
        ethFrame.setEtherType(Ethernet.TYPE_IPV4);
        ethFrame.setVlanID((short) 2);

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

        // UDP datagram
        UDP udpDatagram = new UDP();
        udpDatagram.setSourcePort((byte) UDP.DHCP_CLIENT_PORT);
        udpDatagram.setDestinationPort((byte) UDP.DHCP_SERVER_PORT);

        // DHCP payload
        DHCP dhcp = new DHCP();

        dhcp.setOpCode(DHCP.OPCODE_REQUEST);

        dhcp.setYourIPAddress(0);
        dhcp.setServerIPAddress(0);

        dhcp.setTransactionId(TRANSACTION_ID);
        dhcp.setClientHardwareAddress(CLIENT_HOST.mac().toBytes());
        dhcp.setHardwareType(DHCP.HWTYPE_ETHERNET);
        dhcp.setHardwareAddressLength((byte) 6);

        // DHCP options start...
        DhcpOption option = new DhcpOption();
        List<DhcpOption> optionList = new ArrayList<>();

        // DHCP message type
        option.setCode(OptionCode_MessageType.getValue());
        option.setLength((byte) 1);
        byte[] optionData = {(byte) msgType.getValue()};
        option.setData(optionData);
        optionList.add(option);

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

        // DHCP domain server
        Subnet subnet = dhcpHandler.osNetworkService.subnet("subnet");

        option = new DhcpOption();
        option.setCode(OptionCode_DomainServer.getValue());
        option.setLength((byte) 8);
        ByteBuffer dnsByteBuf = ByteBuffer.allocate(8);
        dnsByteBuf.put(DEFAULT_PRIMARY_DNS.toOctets());
        dnsByteBuf.put(DEFAULT_SECONDARY_DNS.toOctets());
        option.setData(dnsByteBuf.array());
        optionList.add(option);

        // MTU
        option = new DhcpOption();
        option.setCode(DHCP_OPTION_MTU);
        option.setLength((byte) 2);
        option.setData(ByteBuffer.allocate(2).putShort(MTU).array());
        optionList.add(option);

        // classless static route
        option = new DhcpOption();
        option.setCode(OptionCode_Classless_Static_Route.getValue());

        option.setLength((byte) HOST_ROUTES_SIZE);
        ByteBuffer hostRouteByteBuf = ByteBuffer.allocate(HOST_ROUTES_SIZE);

        subnet.getHostRoutes().forEach(h -> {
            IpPrefix ipPrefix = IpPrefix.valueOf(h.getDestination());
            hostRouteByteBuf.put(bytesDestinationDescriptor(ipPrefix));
            hostRouteByteBuf.put(Ip4Address.valueOf(h.getNexthop()).toOctets());
        });

        option.setData(hostRouteByteBuf.array());
        optionList.add(option);

        // default router address setup
        option = new DhcpOption();
        option.setCode(OptionCode_RouterAddress.getValue());
        option.setLength((byte) 4);
        option.setData(Ip4Address.valueOf(subnet.getGateway()).toOctets());
        optionList.add(option);


        // DHCP options end...
        option = new DhcpOption();
        option.setCode(OptionCode_END.getValue());
        option.setLength((byte) 1);
        optionList.add(option);

        dhcp.setOptions(optionList);

        udpDatagram.setPayload(dhcp);
        ipv4Pkt.setPayload(udpDatagram);
        ethFrame.setPayload(ipv4Pkt);

        return ethFrame;
    }

    private byte[] bytesDestinationDescriptor(IpPrefix ipPrefix) {
        ByteBuffer byteBuffer;
        int prefixLen = ipPrefix.prefixLength();

        // retrieve ipPrefix to the destination descriptor format
        // ex) 10.1.1.0/24 -> [10,1,1,0]
        String[] ipPrefixString = ipPrefix.getIp4Prefix().toString()
                .split("/")[0]
                .split("\\.");

        // retrieve destination descriptor and put this to bytebuffer according to RFC 3442
        // ex) 0.0.0.0/0 -> 0
        // ex) 10.0.0.0/8 -> 8.10
        // ex) 10.17.0.0/16 -> 16.10.17
        // ex) 10.27.129.0/24 -> 24.10.27.129
        // ex) 10.229.0.128/25 -> 25.10.229.0.128
        for (int i = 0; i <= 4; i++) {
            if (prefixLen == Math.min(prefixLen, i * 8)) {
                byteBuffer = ByteBuffer.allocate(i + 1);
                byteBuffer.put((byte) prefixLen);

                for (int j = 0; j < i; j++) {
                    byteBuffer.put((byte) Integer.parseInt(ipPrefixString[j]));
                }
                return byteBuffer.array();
            }
        }

        return null;
    }

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

        @Override
        public ApplicationId registerApplication(String name) {
            return new DefaultApplicationId(100, "dhcpTestApp");
        }
    }

    /**
     * Mocks the ComponentConfigRegistry.
     */
    private class TestConfigService extends ComponentConfigAdapter {
    }

    /**
     * Mocks the ClusterService.
     */
    private class TestClusterService extends ClusterServiceAdapter {
    }

    /**
     * Mocks the LeadershipService.
     */
    private class TestLeadershipService extends LeadershipServiceAdapter {
    }

    /**
     * Mocks the InstancePortService.
     */
    private class TestInstancePortService extends InstancePortServiceAdapter {

        @Override
        public InstancePort instancePort(MacAddress macAddress) {
            return new TestInstancePort();
        }
    }

    /**
     * Mocks the OpenstackNetworkService.
     */
    private class TestOpenstackNetworkService extends OpenstackNetworkServiceAdapter {
        @Override
        public Port port(String portId) {
            return new TestPort();
        }

        @Override
        public Subnet subnet(String subnetId) {
            return new TestSubnet();
        }

        @Override
        public Network network(String networkId) {
            return new TestNetwork();
        }

        /**
         * Mocks the Neutron port.
         */
        private class TestPort implements Port {

            @Override
            public State getState() {
                return null;
            }

            @Override
            public boolean isAdminStateUp() {
                return false;
            }

            @Override
            public String getNetworkId() {
                return null;
            }

            @Override
            public String getDeviceId() {
                return null;
            }

            @Override
            public String getDeviceOwner() {
                return null;
            }

            @Override
            public Set<? extends IP> getFixedIps() {
                return ImmutableSet.of(new NeutronIP(EXPECTED_IP, IP_SUBNET_ID));
            }

            @Override
            public Set<? extends AllowedAddressPair> getAllowedAddressPairs() {
                return null;
            }

            @Override
            public String getMacAddress() {
                return null;
            }

            @Override
            public List<String> getSecurityGroups() {
                return null;
            }

            @Override
            public Boolean isPortSecurityEnabled() {
                return null;
            }

            @Override
            public String getHostId() {
                return null;
            }

            @Override
            public String getVifType() {
                return null;
            }

            @Override
            public Map<String, Object> getVifDetails() {
                return null;
            }

            @Override
            public String getvNicType() {
                return null;
            }

            @Override
            public Map<String, Object> getProfile() {
                return null;
            }

            @Override
            public PortBuilder toBuilder() {
                return null;
            }

            @Override
            public String getTenantId() {
                return null;
            }

            @Override
            public void setTenantId(String tenantId) {

            }

            @Override
            public String getName() {
                return null;
            }

            @Override
            public void setName(String name) {

            }

            @Override
            public String getId() {
                return null;
            }

            @Override
            public void setId(String id) {

            }
        }

        /**
         * Mocks the Neutron network.
         */
        private class TestNetwork implements Network {

            @Override
            public State getStatus() {
                return null;
            }

            @Override
            public List<String> getSubnets() {
                return null;
            }

            @Override
            public String getProviderPhyNet() {
                return null;
            }

            @Override
            public boolean isAdminStateUp() {
                return false;
            }

            @Override
            public NetworkType getNetworkType() {
                return null;
            }

            @Override
            public boolean isRouterExternal() {
                return false;
            }

            @Override
            public boolean isShared() {
                return false;
            }

            @Override
            public String getProviderSegID() {
                return null;
            }

            @Override
            public List<? extends Subnet> getNeutronSubnets() {
                return null;
            }

            @Override
            public Integer getMTU() {
                return Integer.valueOf(4000);
            }

            @Override
            public List<String> getAvailabilityZoneHints() {
                return null;
            }

            @Override
            public List<String> getAvailabilityZones() {
                return null;
            }

            @Override
            public NetworkBuilder toBuilder() {
                return null;
            }

            @Override
            public String getTenantId() {
                return null;
            }

            @Override
            public void setTenantId(String s) {

            }

            @Override
            public String getName() {
                return null;
            }

            @Override
            public void setName(String s) {

            }

            @Override
            public String getId() {
                return null;
            }

            @Override
            public void setId(String s) {

            }
        }

        /**
         * Mocks the Neutron subnet.
         */
        private class TestSubnet implements Subnet {

            @Override
            public boolean isDHCPEnabled() {
                return false;
            }

            @Override
            public String getNetworkId() {
                return "1";
            }

            @Override
            public List<String> getDnsNames() {
                List<String> dnsServers = Lists.newArrayList();
                dnsServers.add(DEFAULT_PRIMARY_DNS.toString());
                dnsServers.add(DEFAULT_SECONDARY_DNS.toString());

                return dnsServers;
            }

            @Override
            public List<? extends Pool> getAllocationPools() {
                return null;
            }

            @Override
            public List<? extends HostRoute> getHostRoutes() {
                List<HostRoute> hostRoutes = Lists.newArrayList();

                hostRoutes.add(HOST_ROUTE_1);
                hostRoutes.add(HOST_ROUTE_2);
                hostRoutes.add(HOST_ROUTE_3);
                hostRoutes.add(HOST_ROUTE_4);

                return hostRoutes;
            }

            @Override
            public IPVersionType getIpVersion() {
                return null;
            }

            @Override
            public String getGateway() {
                return EXPECTED_GATEWAY;
            }

            @Override
            public String getCidr() {
                return EXPECTED_CIDR;
            }

            @Override
            public Ipv6AddressMode getIpv6AddressMode() {
                return null;
            }

            @Override
            public Ipv6RaMode getIpv6RaMode() {
                return null;
            }

            @Override
            public SubnetBuilder toBuilder() {
                return null;
            }

            @Override
            public String getTenantId() {
                return null;
            }

            @Override
            public void setTenantId(String tenantId) {

            }

            @Override
            public String getName() {
                return null;
            }

            @Override
            public void setName(String name) {

            }

            @Override
            public String getId() {
                return null;
            }

            @Override
            public void setId(String id) {

            }
        }
    }

    /**
     * Mocks the OpenstackNodeService.
     */
    private class TestOpenstackNodeService extends OpenstackNodeServiceAdapter {

    }

    /**
     * Mocks the OpenstackFlowRuleService.
     */
    private class TestOpenstackFlowRuleService extends OpenstackFlowRuleServiceAdapter {
    }

    /**
     * Mocks the instance port.
     */
    private final class TestInstancePort implements InstancePort {

        @Override
        public String networkId() {
            return null;
        }

        @Override
        public String portId() {
            return null;
        }

        @Override
        public MacAddress macAddress() {
            return null;
        }

        @Override
        public IpAddress ipAddress() {
            return IpAddress.valueOf(EXPECTED_IP);
        }

        @Override
        public DeviceId deviceId() {
            return null;
        }

        @Override
        public DeviceId oldDeviceId() {
            return null;
        }

        @Override
        public PortNumber portNumber() {
            return null;
        }

        @Override
        public PortNumber oldPortNumber() {
            return null;
        }

        @Override
        public State state() {
            return null;
        }

        @Override
        public InstancePort updateState(State newState) {
            return null;
        }

        @Override
        public InstancePort updatePrevLocation(DeviceId oldDeviceId, PortNumber oldPortNumber) {
            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());
            }
        }
    }
}
