/*
 * 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.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.NodeState;
import org.onosproject.openstacknode.api.OpenstackAuth;
import org.onosproject.openstacknode.api.OpenstackNode;
import org.onosproject.openstacknode.api.OpenstackNodeTest;
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.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));
        assertNull(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.
     */
    @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);

        openstackControlNodeV2 = osNodeBuilderV2.hostname("controllerv2")
                .type(OpenstackNode.NodeType.CONTROLLER)
                .managementIp(IpAddress.valueOf("1.1.1.1"))
                .endpoint("1.1.1.1")
                .authentication(osNodeAuthBuilderV2.build())
                .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);

        openstackControlNodeV3 = osNodeBuilderV3.hostname("controllerv3")
                .type(OpenstackNode.NodeType.CONTROLLER)
                .managementIp(IpAddress.valueOf("2.2.2.2"))
                .endpoint("2.2.2.2")
                .authentication(osNodeAuthBuilderV3.build())
                .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);
        }
    }
}
