/*
 * Copyright 2015-present 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.incubator.net.intf.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
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.onlab.packet.VlanId;
import org.onosproject.incubator.net.config.basics.ConfigException;
import org.onosproject.incubator.net.config.basics.InterfaceConfig;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigServiceAdapter;
import org.onosproject.net.host.InterfaceIpAddress;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static junit.framework.TestCase.assertEquals;
import static org.junit.Assert.assertNull;

/**
 * Unit tests for InterfaceManager.
 */
public class InterfaceManagerTest {
    private static final Class<InterfaceConfig> CONFIG_CLASS = InterfaceConfig.class;

    private static final int NUM_INTERFACES = 4;

    private Set<ConnectPoint> subjects = Sets.newHashSet();
    private Map<ConnectPoint, InterfaceConfig> configs = Maps.newHashMap();

    private Set<Interface> interfaces = Sets.newHashSet();

    private NetworkConfigListener listener;

    private InterfaceManager interfaceManager;

    @Before
    public void setUp() throws Exception {
        for (int i = 0; i < NUM_INTERFACES; i++) {
            ConnectPoint cp = createConnectPoint(i);
            subjects.add(cp);

            Interface intf = createInterface(i);

            interfaces.add(intf);

            InterfaceConfig ic = new TestInterfaceConfig(cp, Sets.newHashSet(intf));

            configs.put(cp, ic);
        }

        TestNetworkConfigService configService =
                new TestNetworkConfigService(subjects, configs);

        interfaceManager = new InterfaceManager();
        interfaceManager.configService = configService;
        interfaceManager.activate();
    }

    private Interface createInterface(int i) {
        ConnectPoint cp = createConnectPoint(i);

        InterfaceIpAddress ia = InterfaceIpAddress.valueOf("192.168." + i + ".1/24");

        Interface intf = new Interface(Interface.NO_INTERFACE_NAME, cp,
                Collections.singletonList(ia),
                MacAddress.valueOf(i),
                VlanId.vlanId((short) i));

        return intf;
    }

    private ConnectPoint createConnectPoint(int i) {
        return  ConnectPoint.deviceConnectPoint("of:000000000000000" + i + "/1");
    }

    @Test
    public void testGetInterfaces() throws Exception {
        assertEquals(interfaces, interfaceManager.getInterfaces());
    }

    @Test
    public void testGetInterfacesByPort() throws Exception {
        ConnectPoint cp = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");

        Set<Interface> byPort = Collections.singleton(createInterface(1));

        assertEquals(byPort, interfaceManager.getInterfacesByPort(cp));
    }

    @Test
    public void testGetInterfacesByIp() throws Exception {
        IpAddress ip = Ip4Address.valueOf("192.168.2.1");

        Set<Interface> byIp = Collections.singleton(createInterface(2));

        assertEquals(byIp, interfaceManager.getInterfacesByIp(ip));
    }

    @Test
    public void testGetMatchingInterface() throws Exception {
        IpAddress ip = Ip4Address.valueOf("192.168.1.100");

        Interface matchingIntf = createInterface(1);

        assertEquals(matchingIntf, interfaceManager.getMatchingInterface(ip));

        // Searching for an IP with no match should return null
        ip = Ip4Address.valueOf("1.1.1.1");

        assertNull(interfaceManager.getMatchingInterface(ip));
    }

    @Test
    public void testGetInterfacesByVlan() throws Exception {
        VlanId vlanId = VlanId.vlanId((short) 1);

        Set<Interface> byVlan = Collections.singleton(createInterface(1));

        assertEquals(byVlan, interfaceManager.getInterfacesByVlan(vlanId));
    }

    @Test
    public void testAddInterface() throws Exception {
        // Create a new InterfaceConfig which will get added
        VlanId vlanId = VlanId.vlanId((short) 1);
        ConnectPoint cp = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
        Interface newIntf = new Interface(Interface.NO_INTERFACE_NAME, cp,
                Collections.emptyList(),
                MacAddress.valueOf(100),
                vlanId);

        InterfaceConfig ic = new TestInterfaceConfig(cp, Collections.singleton(newIntf));

        subjects.add(cp);
        configs.put(cp, ic);
        interfaces.add(newIntf);

        NetworkConfigEvent event = new NetworkConfigEvent(
                NetworkConfigEvent.Type.CONFIG_ADDED, cp, CONFIG_CLASS);

        assertEquals(NUM_INTERFACES, interfaceManager.getInterfaces().size());

        // Send in a config event containing a new interface config
        listener.event(event);

        // Check the new interface exists in the InterfaceManager's inventory
        assertEquals(interfaces, interfaceManager.getInterfaces());
        assertEquals(NUM_INTERFACES + 1, interfaceManager.getInterfaces().size());

        // There are now two interfaces with vlan ID 1
        Set<Interface> byVlan = Sets.newHashSet(createInterface(1), newIntf);
        assertEquals(byVlan, interfaceManager.getInterfacesByVlan(vlanId));
    }

    @Test
    public void testUpdateInterface() throws Exception {
        ConnectPoint cp = createConnectPoint(1);

        // Create an interface that is the same as the existing one, but adds a
        // new IP address
        Interface intf = createInterface(1);
        List<InterfaceIpAddress> addresses = Lists.newArrayList(intf.ipAddresses());
        addresses.add(InterfaceIpAddress.valueOf("192.168.100.1/24"));
        intf = new Interface(Interface.NO_INTERFACE_NAME, intf.connectPoint(), addresses, intf.mac(), intf.vlan());

        // Create a new interface on the same connect point as the existing one
        InterfaceIpAddress newAddr = InterfaceIpAddress.valueOf("192.168.101.1/24");
        Interface newIntf = new Interface(Interface.NO_INTERFACE_NAME, cp,
                Collections.singletonList(newAddr),
                MacAddress.valueOf(101),
                VlanId.vlanId((short) 101));

        Set<Interface> interfaces = Sets.newHashSet(intf, newIntf);

        // New interface config updates the existing interface and adds a new
        // interface to the same connect point
        InterfaceConfig ic = new TestInterfaceConfig(cp, interfaces);

        configs.put(cp, ic);

        NetworkConfigEvent event = new NetworkConfigEvent(
                NetworkConfigEvent.Type.CONFIG_UPDATED, cp, CONFIG_CLASS);

        // Send in the event signalling the interfaces for this connect point
        // have been updated
        listener.event(event);

        assertEquals(NUM_INTERFACES + 1, interfaceManager.getInterfaces().size());
        assertEquals(interfaces, interfaceManager.getInterfacesByPort(cp));
    }

    @Test
    public void testRemoveInterface() throws Exception {
        ConnectPoint cp = createConnectPoint(1);

        NetworkConfigEvent event = new NetworkConfigEvent(
                NetworkConfigEvent.Type.CONFIG_REMOVED, cp, CONFIG_CLASS);

        assertEquals(NUM_INTERFACES, interfaceManager.getInterfaces().size());

        // Send in a config event removing an interface config
        listener.event(event);

        assertEquals(NUM_INTERFACES - 1, interfaceManager.getInterfaces().size());
    }

    /**
     * Test version of NetworkConfigService which allows us to pass in subjects
     * and InterfaceConfigs directly.
     */
    private class TestNetworkConfigService extends NetworkConfigServiceAdapter {
        private final Set<ConnectPoint> subjects;
        private final Map<ConnectPoint, InterfaceConfig> configs;

        public TestNetworkConfigService(Set<ConnectPoint> subjects,
                                        Map<ConnectPoint, InterfaceConfig> configs) {
            this.subjects = subjects;
            this.configs = configs;
        }

        @Override
        public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass,
                                                           Class<C> configClass) {
            return (Set<S>) subjects;
        }

        @Override
        public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
            return (C) configs.get(subject);
        }

        @Override
        public void addListener(NetworkConfigListener listener) {
            InterfaceManagerTest.this.listener = listener;
        }
    }

    /**
     * Test version of InterfaceConfig where we can inject interfaces directly,
     * rather than parsing them from JSON.
     */
    private class TestInterfaceConfig extends InterfaceConfig {
        private final ConnectPoint subject;
        private final Set<Interface> interfaces;

        @Override
        public ConnectPoint subject() {
            return subject;
        }

        public TestInterfaceConfig(ConnectPoint subject, Set<Interface> interfaces) {
            this.subject = subject;
            this.interfaces = interfaces;
        }

        @Override
        public Set<Interface> getInterfaces() throws ConfigException {
            return interfaces;
        }
    }

}
