/*
 * 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.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.MoreExecutors;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.mastership.MastershipServiceAdapter;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.host.DefaultHostDescription;
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.host.HostServiceAdapter;
import org.onosproject.net.provider.ProviderId;
import org.openstack4j.model.network.Network;
import org.openstack4j.model.network.NetworkType;
import org.openstack4j.model.network.Port;
import org.openstack4j.openstack.networking.domain.NeutronNetwork;
import org.openstack4j.openstack.networking.domain.NeutronPort;

import java.util.Map;
import java.util.Set;

import static org.junit.Assert.assertEquals;
import static org.onosproject.openstacknetworking.api.Constants.ANNOTATION_NETWORK_ID;
import static org.onosproject.openstacknetworking.api.Constants.ANNOTATION_PORT_ID;

/**
 * Unit tests for Openstack Switching Host Provider.
 */
public class OpenstackSwitchingHostProviderTest {

    private static final String PORT_ID = "65c0ee9f-d634-4522-8954-51021b570b0d";
    private static final String NETWORK_ID = "396f12f8-521e-4b91-8e21-2e003500433a";
    private static final String IP_ADDRESS = "10.10.10.2";
    private static final String SUBNET_ID = "d32019d3-bc6e-4319-9c1d-6722fc136a22";
    private static final String MAC_ADDRESS = "00:11:22:33:44:55";
    private static final String MAC_ADDRESS2 = "11:22:33:44:55:66";

    private static final ProviderId PID = new ProviderId("of", "foo");
    private static final DefaultAnnotations ANNOTATIONS =
                                    DefaultAnnotations.builder()
                                            .set(ANNOTATION_NETWORK_ID, NETWORK_ID)
                                            .set(ANNOTATION_PORT_ID, PORT_ID).build();

    // Host Mac, VLAN
    private static final ProviderId PROVIDER_ID = ProviderId.NONE;
    private static final MacAddress HOST_MAC = MacAddress.valueOf(MAC_ADDRESS);
    private static final MacAddress HOST_MAC2 = MacAddress.valueOf(MAC_ADDRESS2);

    private static final VlanId HOST_VLAN_UNTAGGED = VlanId.NONE;
    private static final HostId HOST_ID_UNTAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_UNTAGGED);

    private static final String SEGMENT_ID = "1";

    // Host IP
    private static final IpAddress HOST_IP11 = IpAddress.valueOf("10.0.1.1");

    // Device
    private static final DeviceId DEV_ID1 = DeviceId.deviceId("of:0000000000000001");
    private static final DeviceId DEV_ID2 = DeviceId.deviceId("of:0000000000000002");

    private static final Device DEV1 =
            new DefaultDevice(PID, DEV_ID1, Device.Type.SWITCH, "", "", "", "", null);
    private static final Device DEV2 =
            new DefaultDevice(PID, DEV_ID2, Device.Type.SWITCH, "", "", "", "", null);

    // Port
    private static final PortNumber P1 = PortNumber.portNumber(1);
    private static final PortNumber P2 = PortNumber.portNumber(2);

    // Connect Point
    private static final ConnectPoint CP11 = new ConnectPoint(DEV_ID1, P1);
    private static final HostLocation HOST_LOC11 = new HostLocation(CP11, 0);
    private static final ConnectPoint CP12 = new ConnectPoint(DEV_ID1, P2);
    private static final HostLocation HOST_LOC12 = new HostLocation(CP12, 0);
    private static final ConnectPoint CP21 = new ConnectPoint(DEV_ID2, P1);

    private Map<HostId, Host> hostMap = Maps.newHashMap();
    private Map<ConnectPoint, MacAddress> macMap = Maps.newHashMap();

    private OpenstackSwitchingHostProvider target;

    private HostDescription resultHostDesc;
    private HostId resultHostId;
    private HostLocation resultHostLocation;

    /**
     * Initial setup for this unit test.
     */
    @Before
    public void setUp() {
        target = new OpenstackSwitchingHostProvider();
        TestUtils.setField(target, "coreService", new TestCoreService());
        TestUtils.setField(target, "deviceService", new TestDeviceService());
        TestUtils.setField(target, "hostService", new TestHostService());
        TestUtils.setField(target, "mastershipService", new TestMastershipService());
        TestUtils.setField(target, "osNodeService", new TestOpenstackNodeService());
        TestUtils.setField(target, "osNetworkService", new TestOpenstackNetworkService());
        TestUtils.setField(target, "hostProviderRegistry", new TestHostProviderRegistry());
        TestUtils.setField(target, "executor", MoreExecutors.newDirectExecutorService());

        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
                Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
        hostMap.put(HOST_ID_UNTAGGED, host1);

        macMap.put(CP11, HOST_MAC);
        macMap.put(CP12, HOST_MAC);
        macMap.put(CP21, HOST_MAC2);

        target.activate();
    }

    /**
     * Tears down this unit test.
     */
    @After
    public void tearDown() {
        target.deactivate();
        target = null;
    }

    /**
     * Tests the process port added method for new addition case.
     */
    @Test
    public void testProcessPortAddedForNewAddition() {
        org.onosproject.net.Port port = new DefaultPort(DEV2, P1, true, ANNOTATIONS);
        target.processPortAdded(port);

        HostId hostId = HostId.hostId(HOST_MAC2);
        HostDescription hostDesc = new DefaultHostDescription(
                HOST_MAC2,
                VlanId.NONE,
                new HostLocation(CP21, System.currentTimeMillis()),
                ImmutableSet.of(),
                ANNOTATIONS

        );

        verifyHostResult(hostId, hostDesc);
    }

    /**
     * Tests the process port added method for updating case.
     */
    @Test
    public void testProcessPortAddedForUpdate() {
        org.onosproject.net.Port port = new DefaultPort(DEV1, P1, true, ANNOTATIONS);
        target.processPortAdded(port);

        HostId hostId = HostId.hostId(HOST_MAC);
        HostDescription hostDesc = new DefaultHostDescription(
                HOST_MAC,
                VlanId.NONE,
                new HostLocation(CP11, System.currentTimeMillis()),
                ImmutableSet.of(),
                ANNOTATIONS
        );

        verifyHostResult(hostId, hostDesc);
    }

    /**
     * Tests the process port added method for migration case.
     */
    @Test
    public void testProcessPortAddedForMigration() {
        org.onosproject.net.Port port = new DefaultPort(DEV1, P2, true, ANNOTATIONS);
        target.processPortAdded(port);

        HostId hostId = HostId.hostId(HOST_MAC);

        verifyHostLocationResult(hostId, HOST_LOC12);
    }

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

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

    /**
     * Mocks the DeviceService.
     */
    private class TestDeviceService extends DeviceServiceAdapter {
    }

    /**
     * Mocks the HostService.
     */
    private class TestHostService extends HostServiceAdapter {

        @Override
        public Host getHost(HostId hostId) {
            return hostMap.get(hostId);
        }
    }

    /**
     * Mocks the HostProviderService.
     */
    private class TestHostProviderService implements HostProviderService {

        @Override
        public void hostDetected(HostId hostId, HostDescription hostDescription,
                                 boolean replaceIps) {
            resultHostId = hostId;
            resultHostDesc = hostDescription;
        }

        @Override
        public void hostVanished(HostId hostId) {

        }

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

        }

        @Override
        public void removeLocationFromHost(HostId hostId, HostLocation location) {

        }

        @Override
        public void addLocationToHost(HostId hostId, HostLocation location) {
            resultHostId = hostId;
            resultHostLocation = location;
        }

        @Override
        public HostProvider provider() {
            return null;
        }
    }

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

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

        @Override
        public void unregister(HostProvider provider) {

        }

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

    /**
     * Mocks the MastershipService.
     */
    private class TestMastershipService extends MastershipServiceAdapter {
    }

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

    /**
     * Mocks the OpenstackNetworkService.
     */
    private class TestOpenstackNetworkService extends OpenstackNetworkServiceAdapter {

        @Override
        public Port port(org.onosproject.net.Port port) {
            Port osPort = NeutronPort.builder()
                                        .networkId(NETWORK_ID)
                                        .fixedIp(IP_ADDRESS, SUBNET_ID)
                                        .macAddress(macMap.get(
                                                new ConnectPoint(port.element().id(),
                                                        port.number())).toString())
                                        .build();
            osPort.setId(PORT_ID);

            return osPort;
        }

        @Override
        public Network network(String networkId) {
            Network osNetwork = NeutronNetwork.builder()
                                        .networkType(NetworkType.VXLAN)
                                        .segmentId(SEGMENT_ID)
                                        .build();
            osNetwork.setId(NETWORK_ID);
            return osNetwork;
        }
    }

    /**
     * Verifies the HostId and HostDescription.
     *
     * @param hostId        host identifier
     * @param hostDesc      host description
     */
    private void verifyHostResult(HostId hostId, HostDescription hostDesc) {
        assertEquals(hostId, resultHostId);
        assertEquals(hostDesc.hwAddress(), resultHostDesc.hwAddress());
        assertEquals(hostDesc.annotations().value(NETWORK_ID),
                resultHostDesc.annotations().value(NETWORK_ID));
    }

    /**
     * Verifies the HostId and HostLocation.
     *
     * @param hostId        host identifier
     * @param hostLocation  host location
     */
    private void verifyHostLocationResult(HostId hostId, HostLocation hostLocation) {
        assertEquals(hostId, resultHostId);
        assertEquals(hostLocation.deviceId(), resultHostLocation.deviceId());
        assertEquals(hostLocation.port(), resultHostLocation.port());
    }
}
