/*
 * Copyright 2015-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.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.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.ipAddressesList());
        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;
        }
    }

}
