/*
 * Copyright 2017-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.routing.impl;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.incubator.net.intf.InterfaceEvent;
import org.onosproject.incubator.net.intf.InterfaceListener;
import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.net.DeviceId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Stream;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Manages which interfaces are part of the router when the configuration is
 * updated, and handles the provisioning/unprovisioning of interfaces when they
 * are added/removed.
 */
public class RouterInterfaceManager {

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

    private final Consumer<Interface> provisioner;
    private final Consumer<Interface> unprovisioner;

    private Set<String> configuredInterfaces = Collections.emptySet();
    private Set<Interface> provisioned = new HashSet<>();

    private InterfaceService interfaceService;
    private InterfaceListener listener = new InternalInterfaceListener();

    private final DeviceId routerDeviceId;

    /**
     * Creates a new router interface manager.
     *
     * @param deviceId router device ID
     * @param configuredInterfaces names of interfaces configured for this router
     * @param interfaceService interface service
     * @param provisioner consumer that will provision new interfaces
     * @param unprovisioner consumer that will unprovision old interfaces
     */
    public RouterInterfaceManager(DeviceId deviceId,
                                  Set<String> configuredInterfaces,
                                  InterfaceService interfaceService,
                                  Consumer<Interface> provisioner,
                                  Consumer<Interface> unprovisioner) {
        this.routerDeviceId = checkNotNull(deviceId);
        this.provisioner = checkNotNull(provisioner);
        this.unprovisioner = checkNotNull(unprovisioner);
        this.interfaceService = checkNotNull(interfaceService);
        this.configuredInterfaces = checkNotNull(configuredInterfaces);

        provision();

        interfaceService.addListener(listener);
    }

    /**
     * Cleans up the router and unprovisions all interfaces.
     */
    public void cleanup() {
        interfaceService.removeListener(listener);

        unprovision();
    }

    /**
     * Retrieves the set of configured interface names.
     *
     * @return interface names
     */
    public Set<String> configuredInterfaces() {
        return configuredInterfaces;
    }

    /**
     * Changes the set of interfaces configured on the router.
     *
     * @param newConfiguredInterfaces new set of router interfaces
     */
    public void changeConfiguredInterfaces(Set<String> newConfiguredInterfaces) {
        Set<String> oldConfiguredInterfaces = configuredInterfaces;
        configuredInterfaces = ImmutableSet.copyOf(newConfiguredInterfaces);

        if (newConfiguredInterfaces.isEmpty() && !oldConfiguredInterfaces.isEmpty()) {
            // Reverted to using all interfaces. Provision interfaces that
            // weren't previously in the configured list
            getInterfacesForDevice(routerDeviceId)
                    .filter(intf -> !oldConfiguredInterfaces.contains(intf.name()))
                    .forEach(this::provision);
        } else if (!newConfiguredInterfaces.isEmpty() && oldConfiguredInterfaces.isEmpty()) {
            // Began using an interface list. Unprovision interfaces that
            // are not in the new interface list.
            getInterfacesForDevice(routerDeviceId)
                    .filter(intf -> !newConfiguredInterfaces.contains(intf.name()))
                    .forEach(this::unprovision);
        } else {
            // The existing interface list was changed.
            Set<String> toUnprovision = Sets.difference(oldConfiguredInterfaces, newConfiguredInterfaces);
            Set<String> toProvision = Sets.difference(newConfiguredInterfaces, oldConfiguredInterfaces);

            toUnprovision.forEach(name ->
                    getInterfacesForDevice(routerDeviceId)
                            .filter(intf -> intf.name().equals(name))
                            .findFirst()
                            .ifPresent(this::unprovision)
            );

            toProvision.forEach(name ->
                    getInterfacesForDevice(routerDeviceId)
                            .filter(intf -> intf.name().equals(name))
                            .findFirst()
                            .ifPresent(this::provision)
            );
        }

        configuredInterfaces = newConfiguredInterfaces;
    }

    private void provision() {
        getInterfacesForDevice(routerDeviceId)
                .filter(this::shouldUse)
                .forEach(this::provision);
    }

    private void unprovision() {
        getInterfacesForDevice(routerDeviceId)
                .filter(this::shouldUse)
                .forEach(this::unprovision);
    }

    private void provision(Interface intf) {
        if (!provisioned.contains(intf) && shouldUse(intf)) {
            log.info("Provisioning interface {}", intf);
            provisioner.accept(intf);
            provisioned.add(intf);
        }
    }

    private void unprovision(Interface intf) {
        if (provisioned.contains(intf)) {
            log.info("Unprovisioning interface {}", intf);
            unprovisioner.accept(intf);
            provisioned.remove(intf);
        }
    }

    private boolean shouldUse(Interface intf) {
        return configuredInterfaces.isEmpty() || configuredInterfaces.contains(intf.name());
    }

    private Stream<Interface> getInterfacesForDevice(DeviceId deviceId) {
        return interfaceService.getInterfaces().stream()
                .filter(intf -> intf.connectPoint().deviceId().equals(deviceId));
    }

    private class InternalInterfaceListener implements InterfaceListener {
        @Override
        public void event(InterfaceEvent event) {
            Interface intf = event.subject();
            switch (event.type()) {
            case INTERFACE_ADDED:
                provision(intf);
                break;
            case INTERFACE_UPDATED:
                // TODO
                break;
            case INTERFACE_REMOVED:
                unprovision(intf);
                break;
            default:
                break;
            }
        }
    }
}
