/*
 * 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.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.IpAddress;
import org.onlab.packet.VlanId;
import org.onosproject.event.ListenerRegistry;
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.intf.InterfaceAdminService;
import org.onosproject.net.intf.InterfaceEvent;
import org.onosproject.net.intf.InterfaceListener;
import org.onosproject.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;

import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toSet;

/**
 * Manages the inventory of interfaces in the system.
 */
@Service
@Component(immediate = true)
public class InterfaceManager extends ListenerRegistry<InterfaceEvent, InterfaceListener>
        implements InterfaceService, InterfaceAdminService {

    private final Logger log = LoggerFactory.getLogger(getClass());

    private static final Class<ConnectPoint> SUBJECT_CLASS = ConnectPoint.class;
    private static final Class<InterfaceConfig> CONFIG_CLASS = InterfaceConfig.class;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigService configService;

    private final InternalConfigListener listener = new InternalConfigListener();

    private final Map<ConnectPoint, Set<Interface>> interfaces = Maps.newConcurrentMap();

    @Activate
    public void activate() {
        configService.addListener(listener);

        // TODO address concurrency issues here
        for (ConnectPoint subject : configService.getSubjects(SUBJECT_CLASS, CONFIG_CLASS)) {
            InterfaceConfig config = configService.getConfig(subject, CONFIG_CLASS);

            if (config != null) {
                updateInterfaces(config);
            }
        }

        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        configService.removeListener(listener);

        log.info("Stopped");
    }

    @Override
    public Set<Interface> getInterfaces() {
        return interfaces.values()
                .stream()
                .flatMap(set -> set.stream())
                .collect(collectingAndThen(toSet(), ImmutableSet::copyOf));
    }

    @Override
    public Interface getInterfaceByName(ConnectPoint connectPoint, String name) {
        Optional<Interface> intf =
                interfaces.getOrDefault(connectPoint, Collections.emptySet())
                .stream()
                .filter(i -> i.name().equals(name))
                .findAny();

        return intf.orElse(null);
    }

    @Override
    public Set<Interface> getInterfacesByPort(ConnectPoint port) {
        Set<Interface> intfs = interfaces.get(port);
        if (intfs == null) {
            return Collections.emptySet();
        }
        return ImmutableSet.copyOf(intfs);
    }

    @Override
    public Set<Interface> getInterfacesByIp(IpAddress ip) {
        return interfaces.values()
                .stream()
                .flatMap(Collection::stream)
                .filter(intf -> intf.ipAddressesList()
                        .stream()
                        .anyMatch(ia -> ia.ipAddress().equals(ip)))
                .collect(collectingAndThen(toSet(), ImmutableSet::copyOf));
    }

    @Override
    public Interface getMatchingInterface(IpAddress ip) {
        return getMatchingInterfacesStream(ip).findFirst().orElse(null);
    }

    @Override
    public Set<Interface> getMatchingInterfaces(IpAddress ip) {
        return getMatchingInterfacesStream(ip).collect(toSet());
    }

    private Stream<Interface> getMatchingInterfacesStream(IpAddress ip) {
        return interfaces.values()
                .stream()
                .flatMap(Collection::stream)
                .filter(intf -> intf.ipAddressesList()
                        .stream()
                        .anyMatch(intfIp -> intfIp.subnetAddress().contains(ip)));
    }

    @Override
    public Set<Interface> getInterfacesByVlan(VlanId vlan) {
        return interfaces.values()
                .stream()
                .flatMap(Collection::stream)
                .filter(intf -> intf.vlan().equals(vlan))
                .collect(collectingAndThen(toSet(), ImmutableSet::copyOf));
    }

    private void updateInterfaces(InterfaceConfig intfConfig) {
        try {
            Set<Interface> old = interfaces.put(intfConfig.subject(),
                    Sets.newHashSet(intfConfig.getInterfaces()));

            if (old == null) {
                old = Collections.emptySet();
            }

            for (Interface intf : intfConfig.getInterfaces()) {
                if (intf.name().equals(Interface.NO_INTERFACE_NAME)) {
                    process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_ADDED, intf));
                } else {
                    Optional<Interface> oldIntf = findInterface(intf, old);
                    if (oldIntf.isPresent()) {
                        old.remove(oldIntf.get());
                        if (!oldIntf.get().equals(intf)) {
                            process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_UPDATED, intf, oldIntf.get()));
                        }
                    } else {
                        process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_ADDED, intf));
                    }
                }
            }

            for (Interface intf : old) {
                if (!intf.name().equals(Interface.NO_INTERFACE_NAME)) {
                    process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_REMOVED, intf));
                }
            }
        } catch (ConfigException e) {
            log.error("Error in interface config", e);
        }
    }

    private Optional<Interface> findInterface(Interface intf, Set<Interface> set) {
        return set.stream().filter(i -> i.name().equals(intf.name())).findAny();
    }

    private void removeInterfaces(ConnectPoint port) {
        Set<Interface> old = interfaces.remove(port);

        old.stream()
                .filter(i -> !i.name().equals(Interface.NO_INTERFACE_NAME))
                .forEach(i -> process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_REMOVED, i)));
    }

    @Override
    public void add(Interface intf) {
        InterfaceConfig config =
                configService.addConfig(intf.connectPoint(), CONFIG_CLASS);

        config.addInterface(intf);

        configService.applyConfig(intf.connectPoint(), CONFIG_CLASS, config.node());
    }

    @Override
    public boolean remove(ConnectPoint connectPoint, String name) {
        InterfaceConfig config = configService.addConfig(connectPoint, CONFIG_CLASS);
        config.removeInterface(name);

        try {
            if (config.getInterfaces().isEmpty()) {
                configService.removeConfig(connectPoint, CONFIG_CLASS);
            } else {
                configService.applyConfig(connectPoint, CONFIG_CLASS, config.node());
            }
        } catch (ConfigException e) {
            log.error("Error reading interfaces JSON", e);
            return false;
        }

        return true;
    }

    /**
     * Listener for network config events.
     */
    private class InternalConfigListener implements NetworkConfigListener {

        @Override
        public void event(NetworkConfigEvent event) {
            if (event.configClass() == CONFIG_CLASS) {
                switch (event.type()) {
                case CONFIG_ADDED:
                case CONFIG_UPDATED:
                    InterfaceConfig config =
                            configService.getConfig((ConnectPoint) event.subject(), InterfaceConfig.class);
                    updateInterfaces(config);
                    break;
                case CONFIG_REMOVED:
                    removeInterfaces((ConnectPoint) event.subject());
                    break;
                case CONFIG_REGISTERED:
                case CONFIG_UNREGISTERED:
                default:
                    break;
                }
            }
        }
    }
}
