/*
 * 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.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.testing.EqualsTester;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.openstacknetworking.api.Constants;
import org.onosproject.openstacknetworking.api.InstancePort;
import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
import org.onosproject.openstacknetworking.api.OpenstackRouterAdminService;
import org.onosproject.openstacknetworking.impl.DefaultInstancePort;
import org.onosproject.openstacknetworking.impl.OpenstackNetworkServiceAdapter;
import org.onosproject.openstacknetworking.impl.OpenstackRouterServiceAdapter;
import org.onosproject.openstacknetworking.impl.TestRouterInterface;
import org.onosproject.openstacknetworking.web.OpenstackFloatingIpWebResourceTest;
import org.onosproject.openstacknetworking.web.OpenstackNetworkWebResourceTest;
import org.onosproject.openstacknode.api.DefaultOpenstackAuth;
import org.onosproject.openstacknode.api.DefaultOpenstackNode;
import org.onosproject.openstacknode.api.KeystoneConfig;
import org.onosproject.openstacknode.api.NodeState;
import org.onosproject.openstacknode.api.OpenstackAuth;
import org.onosproject.openstacknode.api.OpenstackNode;
import org.onosproject.openstacknode.api.OpenstackNodeTest;
import org.onosproject.openstacknode.api.DefaultKeystoneConfig;
import org.openstack4j.model.network.NetFloatingIP;
import org.openstack4j.model.network.Network;
import org.openstack4j.model.network.Port;
import org.openstack4j.model.network.RouterInterface;
import org.openstack4j.openstack.networking.domain.NeutronFloatingIP;
import org.openstack4j.openstack.networking.domain.NeutronNetwork;
import org.openstack4j.openstack.networking.domain.NeutronPort;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.onosproject.openstacknetworking.api.Constants.UNSUPPORTED_VENDOR;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.addRouterIface;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.associatedFloatingIp;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.checkArpMode;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getConnectedClient;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByComputeDevId;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByInstancePort;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getIntfNameFromPciAddress;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.isAssociatedWithVM;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.jsonToModelEntity;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.modelEntityToJson;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.prettyJson;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.routerInterfacesEquals;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.vnicType;

public final class OpenstackNetworkingUtilTest {

    private NetFloatingIP floatingIp1;
    private NetFloatingIP floatingIp2;
    private NetFloatingIP floatingIp3;
    private Port openstackPort;
    private Port openstackSriovPort1;
    private Port openstackSriovPort2;
    private Port openstackSriovPort3;
    private InstancePort instancePort1;
    private InstancePort instancePort2;
    private InstancePort instancePort3;
    private Map<String, RouterInterface> routerInterfaceMap = Maps.newHashMap();
    private OpenstackNode openstackControlNodeV2;
    private OpenstackNode openstackControlNodeV3;

    @Before
    public void setUp() {

        instancePort1 = DefaultInstancePort.builder()
                .networkId("net-id-1")
                .portId("ce705c24-c1ef-408a-bda3-7bbd946164ab")
                .deviceId(DeviceId.deviceId("of:000000000000000a"))
                .portNumber(PortNumber.portNumber(1, "tap-1"))
                .ipAddress(IpAddress.valueOf("10.0.0.3"))
                .macAddress(MacAddress.valueOf("11:22:33:44:55:66"))
                .state(InstancePort.State.valueOf("ACTIVE"))
                .build();

        instancePort2 = DefaultInstancePort.builder()
                .networkId("net-id-2")
                .portId("port-id-2")
                .deviceId(DeviceId.deviceId("of:000000000000000b"))
                .portNumber(PortNumber.portNumber(2, "tap-2"))
                .ipAddress(IpAddress.valueOf("10.10.10.2"))
                .macAddress(MacAddress.valueOf("22:33:44:55:66:11"))
                .state(InstancePort.State.valueOf("ACTIVE"))
                .build();

        instancePort3 = DefaultInstancePort.builder()
                .networkId("net-id-3")
                .portId("port-id-3")
                .deviceId(DeviceId.deviceId("of:000000000000000c"))
                .oldDeviceId(DeviceId.deviceId("of:000000000000000d"))
                .oldPortNumber(PortNumber.portNumber(4, "tap-4"))
                .portNumber(PortNumber.portNumber(3, "tap-3"))
                .ipAddress(IpAddress.valueOf("10.10.10.3"))
                .macAddress(MacAddress.valueOf("33:44:55:66:11:22"))
                .state(InstancePort.State.valueOf("ACTIVE"))
                .build();

        InputStream floatingIpjsonStream1 = OpenstackFloatingIpWebResourceTest.class
                .getResourceAsStream("openstack-floatingip1.json");
        InputStream floatingIpjsonStream2 = OpenstackFloatingIpWebResourceTest.class
                .getResourceAsStream("openstack-floatingip2.json");
        InputStream floatingIpjsonStream3 = OpenstackFloatingIpWebResourceTest.class
                .getResourceAsStream("openstack-floatingip3.json");

        floatingIp1 = (NetFloatingIP)
                jsonToModelEntity(floatingIpjsonStream1, NeutronFloatingIP.class);
        floatingIp2 = (NetFloatingIP)
                jsonToModelEntity(floatingIpjsonStream2, NeutronFloatingIP.class);
        floatingIp3 = (NetFloatingIP)
                jsonToModelEntity(floatingIpjsonStream3, NeutronFloatingIP.class);

        InputStream portJsonStream = OpenstackNetworkWebResourceTest.class
                .getResourceAsStream("openstack-port.json");

        InputStream sriovPortJsonStream1 = OpenstackNetworkWebResourceTest.class
                .getResourceAsStream("openstack-port-sriov1.json");
        InputStream sriovPortJsonStream2 = OpenstackNetworkWebResourceTest.class
                .getResourceAsStream("openstack-port-sriov2.json");
        InputStream sriovPortJsonStream3 = OpenstackNetworkWebResourceTest.class
                .getResourceAsStream("openstack-port-sriov3.json");

        openstackPort = (Port)
                jsonToModelEntity(portJsonStream, NeutronPort.class);

        openstackSriovPort1 = (Port)
                jsonToModelEntity(sriovPortJsonStream1, NeutronPort.class);
        openstackSriovPort2 = (Port)
                jsonToModelEntity(sriovPortJsonStream2, NeutronPort.class);
        openstackSriovPort3 = (Port)
                jsonToModelEntity(sriovPortJsonStream3, NeutronPort.class);
    }

    @After
    public void tearDown() {
    }

    /**
     * Tests the floatingIp translation.
     */
    @Test
    public void testFloatingIp() throws IOException {
        ObjectNode floatingIpNode =
                modelEntityToJson(floatingIp1, NeutronFloatingIP.class);
        InputStream is = IOUtils.toInputStream(floatingIpNode.toString(), StandardCharsets.UTF_8.name());
        NetFloatingIP floatingIp2 = (NetFloatingIP)
                jsonToModelEntity(is, NeutronFloatingIP.class);
        new EqualsTester().addEqualityGroup(floatingIp1, floatingIp2).testEquals();
    }

    /**
     * Tests the associatedFloatingIp method.
     */
    @Test
    public void testAsscoatedFloatingIp() throws NullPointerException {
        Set<NetFloatingIP> testSet = Sets.newHashSet();
        testSet.add(floatingIp1);
        testSet.add(floatingIp2);
        testSet.add(floatingIp3);

        NetFloatingIP floatingIp1 = associatedFloatingIp(instancePort1, testSet);
        NetFloatingIP floatingIp2 = associatedFloatingIp(instancePort2, testSet);

        assertEquals(floatingIp1, this.floatingIp1);
        assertEquals(floatingIp2, null);
    }

    /**
     * Tests the isAssociatedWithVM method.
     */
    @Test
    public void testIsAssociatedWithVM() {
        OpenstackNetworkService service = new TestOpenstackNetworkService();
        NetFloatingIP floatingIp4 = new NeutronFloatingIP().toBuilder().portId("portId4").build();

        assertFalse(isAssociatedWithVM(service, floatingIp4));
        assertFalse(isAssociatedWithVM(service, floatingIp3));
        assertTrue(isAssociatedWithVM(service, floatingIp1));
    }

    /**
     * Tests the isAssociatedWithVM method in case IllegalStateException is occurred.
     */
    @Test(expected = IllegalStateException.class)
    public void testIsAssociatedWithVMexceptionCase() {
        OpenstackNetworkService service = new TestOpenstackNetworkService();
        isAssociatedWithVM(service, floatingIp2);
    }


    /**
     * Tests the getGwByInstancePort method.
     */
    @Test
    public void testGetGwByInstancePort() {

        Set<OpenstackNode> gws = Sets.newConcurrentHashSet();
        gws.add(genGateway(1));
        gws.add(genGateway(2));
        gws.add(genGateway(3));

        int expectedGwIndex = 2;

        OpenstackNode gw = getGwByInstancePort(gws, instancePort1);

        assertEquals(genGateway(expectedGwIndex), gw);

        assertNull(getGwByInstancePort(gws, null));
    }

    /**
     * Tests the getGwByComputeDevId method.
     */
    @Test
    public void testGetGwByComputeDevId() {
        Set<OpenstackNode> gws = Sets.newConcurrentHashSet();

        OpenstackNode nullGw = getGwByComputeDevId(gws, genDeviceId(1));
        assertNull(nullGw);

        gws.add(genGateway(1));
        gws.add(genGateway(2));
        gws.add(genGateway(3));

        Set<OpenstackNode> cloneOfGws = ImmutableSet.copyOf(gws);

        Map<String, Integer> gwCountMap = Maps.newConcurrentMap();
        int numOfDev = 99;

        for (int i = 1; i < 1 + numOfDev; i++) {
            OpenstackNode gw = getGwByComputeDevId(gws, genDeviceId(i));

            if (gwCountMap.get(gw.hostname()) == null) {
                gwCountMap.put(gw.hostname(), 1);
            } else {
                gwCountMap.compute(gw.hostname(), (k, v) -> v + 1);
            }

            new EqualsTester().addEqualityGroup(
                    getGwByComputeDevId(gws, genDeviceId(i)),
                    getGwByComputeDevId(cloneOfGws, genDeviceId(i)))
                    .testEquals();
        }

        int sum = gwCountMap.values().stream().mapToInt(Integer::intValue).sum();
        assertEquals(numOfDev, sum);
    }

    /**
     * Tests getIntfNameFromPciAddress method.
     */
    @Test
    public void testGetIntfNameFromPciAddress() {

        String expectedIntfName1 = "enp5s8";
        String expectedIntfName2 = "enp5s8f3";

        assertNull(getIntfNameFromPciAddress(openstackPort));
        assertEquals(expectedIntfName1, getIntfNameFromPciAddress(openstackSriovPort1));
        assertEquals(expectedIntfName2, getIntfNameFromPciAddress(openstackSriovPort2));
        assertEquals(UNSUPPORTED_VENDOR, getIntfNameFromPciAddress(openstackSriovPort3));
    }

    /**
     * Tests swapStaleLocation method.
     */
    @Test
    public void testSwapStaleLocation() {
        InstancePort swappedInstancePort =  swapStaleLocation(instancePort3);

        assertEquals(instancePort3.oldDeviceId(), swappedInstancePort.deviceId());
        assertEquals(instancePort3.oldPortNumber(), swappedInstancePort.portNumber());

    }

    /**
     * Tests hasIntfAleadyInDevice method.
     */
    @Test
    public void testHasIntfAleadyInDevice() {
        DeviceService deviceService = new TestDeviceService();
        assertTrue(OpenstackNetworkingUtil.hasIntfAleadyInDevice(DeviceId.deviceId("deviceId"),
                "port1", deviceService));
        assertTrue(OpenstackNetworkingUtil.hasIntfAleadyInDevice(DeviceId.deviceId("deviceId"),
                "port2", deviceService));
        assertTrue(OpenstackNetworkingUtil.hasIntfAleadyInDevice(DeviceId.deviceId("deviceId"),
                "port3", deviceService));
        assertFalse(OpenstackNetworkingUtil.hasIntfAleadyInDevice(DeviceId.deviceId("deviceId"),
                "port4", deviceService));
    }

    /**
     * Tests addRouterIface method.
     */
    @Test
    public void testAddRouterIface() {
        OpenstackRouterAdminService service = new TestOpenstackRouterAdminService();

        addRouterIface(openstackPort, service);
        RouterInterface initialRouterInterface = new TestRouterInterface(openstackPort.getDeviceId(),
                openstackPort.getFixedIps().stream().findAny().get().getSubnetId(),
                openstackPort.getId(),
                openstackPort.getTenantId());

        assertTrue(routerInterfacesEquals(initialRouterInterface, service.routerInterface(openstackPort.getId())));

        addRouterIface(openstackSriovPort1, service);
        RouterInterface updatedInitialRouterInterface = new TestRouterInterface(openstackSriovPort1.getDeviceId(),
                openstackSriovPort1.getFixedIps().stream().findAny().get().getSubnetId(),
                openstackSriovPort1.getId(),
                openstackSriovPort1.getTenantId());

        assertTrue(routerInterfacesEquals(
                updatedInitialRouterInterface, service.routerInterface(openstackSriovPort1.getId())));
    }

    /**
     * Util for generating dummy gateway node.
     *
     * @param index dummy gateway number
     * @return dummy gateway node
     */
    public OpenstackNode genGateway(int index) {
        Device intgBrg = InternalOpenstackNodeTest.createDevice(index);

        String hostname = "gateway-" + index;
        IpAddress ip = Ip4Address.valueOf("10.10.10." + index);
        NodeState state = NodeState.COMPLETE;
        String uplinkPort = "eth0";
        return InternalOpenstackNodeTest.createNode(hostname,
                OpenstackNode.NodeType.GATEWAY, intgBrg, ip, uplinkPort, state);
    }

    /**
     * Tests the testPrettyJson method.
     */
    @Test
    public void testPrettyJson() {
        String string = prettyJson(new ObjectMapper(), "{\"json\":\"json\"}");
        String prettyJsonString = "{\n  \"json\" : \"json\"\n}";
        assertEquals(string, prettyJsonString);

        assertNull(prettyJson(new ObjectMapper(), "{\"json\":\"json\""));
        assertNull(prettyJson(new ObjectMapper(), "{\"json\"\"json\"}"));
    }

    /**
     * Tests the checkArpMode method.
     */
    @Test
    public void testCheckArpMode() {
        assertFalse(checkArpMode(null));
        assertTrue(checkArpMode("proxy"));
        assertTrue(checkArpMode("broadcast"));
    }

    /**
     * Tests the getConnectedClient method.
     */
    @Ignore
    @Test
    public void testGetConnectedClient() {
        OpenstackNode.Builder osNodeBuilderV2 = DefaultOpenstackNode.builder();
        OpenstackAuth.Builder osNodeAuthBuilderV2 = DefaultOpenstackAuth.builder()
                .version("v2.0")
                .protocol(OpenstackAuth.Protocol.HTTP)
                .project("admin")
                .username("admin")
                .password("password")
                .perspective(OpenstackAuth.Perspective.PUBLIC);

        String endpointV2 = "1.1.1.1:35357/v2.0";

        KeystoneConfig keystoneConfigV2 = DefaultKeystoneConfig.builder()
                .authentication(osNodeAuthBuilderV2.build())
                .endpoint(endpointV2)
                .build();

        openstackControlNodeV2 = osNodeBuilderV2.hostname("controllerv2")
                .type(OpenstackNode.NodeType.CONTROLLER)
                .managementIp(IpAddress.valueOf("1.1.1.1"))
                .keystoneConfig(keystoneConfigV2)
                .state(NodeState.COMPLETE)
                .build();

        OpenstackNode.Builder osNodeBuilderV3 = DefaultOpenstackNode.builder();
        OpenstackAuth.Builder osNodeAuthBuilderV3 = DefaultOpenstackAuth.builder()
                .version("v2")
                .protocol(OpenstackAuth.Protocol.HTTP)
                .project("admin")
                .username("admin")
                .password("password")
                .perspective(OpenstackAuth.Perspective.PUBLIC);

        String endpointV3 = "2.2.2.2:80/v3";

        KeystoneConfig keystoneConfigV3 = DefaultKeystoneConfig.builder()
                .authentication(osNodeAuthBuilderV3.build())
                .endpoint(endpointV3)
                .build();

        openstackControlNodeV3 = osNodeBuilderV3.hostname("controllerv3")
                .type(OpenstackNode.NodeType.CONTROLLER)
                .managementIp(IpAddress.valueOf("2.2.2.2"))
                .keystoneConfig(keystoneConfigV3)
                .state(NodeState.COMPLETE)
                .build();

        getConnectedClient(openstackControlNodeV2);
        getConnectedClient(openstackControlNodeV3);
    }

    /**
     * Tests the vnicType method.
     */
    @Test
    public void testVnicType() {
        String portNameNormalTap = "tap123456789ab";
        String portNameNormalVhu = "tap123456789ab";
        String portNameNormalCavium = "enp1f2s3";
        String portNameUnsupported = "123456789ab";

        assertEquals(vnicType(portNameNormalTap), Constants.VnicType.NORMAL);
        assertEquals(vnicType(portNameNormalVhu), Constants.VnicType.NORMAL);
        assertEquals(vnicType(portNameNormalCavium), Constants.VnicType.DIRECT);
        assertEquals(vnicType(portNameUnsupported), Constants.VnicType.UNSUPPORTED);
    }

    private DeviceId genDeviceId(int index) {
        return DeviceId.deviceId("of:compute-" + index);
    }

    protected class InternalOpenstackNodeTest extends OpenstackNodeTest {
    }

    /**
     * Mocks the DeviceService.
     */
    private class TestDeviceService extends DeviceServiceAdapter {
        @Override
        public List<org.onosproject.net.Port> getPorts(DeviceId deviceId) {
            List<org.onosproject.net.Port> ports = Lists.newArrayList();
            DefaultAnnotations.Builder annotations1 = DefaultAnnotations.builder()
                    .set(PORT_NAME, "port1");
            DefaultAnnotations.Builder annotations2 = DefaultAnnotations.builder()
                    .set(PORT_NAME, "port2");
            DefaultAnnotations.Builder annotations3 = DefaultAnnotations.builder()
                    .set(PORT_NAME, "port3");

            org.onosproject.net.Port port1 = new DefaultPort(null, PortNumber.portNumber(1),
                    true, annotations1.build());
            org.onosproject.net.Port port2 = new DefaultPort(null, PortNumber.portNumber(2),
                    true, annotations2.build());
            org.onosproject.net.Port port3 = new DefaultPort(null, PortNumber.portNumber(3),
                    true, annotations3.build());

            ports.add(port1);
            ports.add(port2);
            ports.add(port3);

            return ports;
        }
    }

    private class TestOpenstackNetworkService extends OpenstackNetworkServiceAdapter {
        @Override
        public Network network(String networkId) {
            if (networkId.equals(openstackSriovPort1.getNetworkId())) {
                return new NeutronNetwork().toBuilder().name("network").build();
            } else {
                return null;
            }
        }

        @Override
        public Port port(String portId) {
            if (portId.equals(floatingIp1.getPortId())) {
                return openstackSriovPort1;
            } else if (portId.equals(floatingIp2.getPortId())) {
                return openstackSriovPort2;
            } else if (portId.equals("portId4")) {
                return new NeutronPort().toBuilder().name("osPort4").build();
            } else {
                return null;
            }
        }
    }

    private class TestOpenstackRouterAdminService extends OpenstackRouterServiceAdapter {
        @Override
        public void addRouterInterface(RouterInterface osRouterIface) {
            routerInterfaceMap.put(osRouterIface.getPortId(), osRouterIface);
        }

        @Override
        public void updateRouterInterface(RouterInterface osRouterIface) {
            routerInterfaceMap.put(osRouterIface.getPortId(), osRouterIface);
        }

        @Override
        public RouterInterface routerInterface(String osRouterIfaceId) {
            return routerInterfaceMap.get(osRouterIfaceId);
        }
    }
}
