/*
 * Copyright 2016-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
 */
package org.onosproject.vpls;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.SetMultimap;
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.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.app.ApplicationService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
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.EncapsulationType;
import org.onosproject.net.FilteredConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.Key;
import org.onosproject.routing.IntentSynchronizationService;
import org.onosproject.vpls.config.VplsConfigService;
import org.slf4j.Logger;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static org.onosproject.vpls.IntentInstaller.PREFIX_BROADCAST;
import static org.onosproject.vpls.IntentInstaller.PREFIX_UNICAST;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Application to create L2 broadcast overlay networks using VLANs.
 */
@Component(immediate = true)
public class Vpls {
    static final String VPLS_APP = "org.onosproject.vpls";

    private static final String HOST_FCP_NOT_FOUND =
            "Filtered connected point for host {} not found";
    private static final String HOST_EVENT = "Received HostEvent {}";
    private static final String INTF_CONF_EVENT =
            "Received InterfaceConfigEvent {}";
    private static final String NET_CONF_EVENT =
            "Received NetworkConfigEvent {}";

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ApplicationService applicationService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected HostService hostService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected IntentService intentService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected InterfaceService interfaceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected IntentSynchronizationService intentSynchronizer;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected VplsConfigService vplsConfigService;

    private final HostListener hostListener = new InternalHostListener();

    private final InternalInterfaceListener interfaceListener =
            new InternalInterfaceListener();

    private final InternalNetworkConfigListener configListener =
            new InternalNetworkConfigListener();

    private IntentInstaller intentInstaller;

    private ApplicationId appId;


    @Activate
    public void activate() {
        appId = coreService.registerApplication(VPLS_APP);

        intentInstaller = new IntentInstaller(appId,
                                              intentService,
                                              intentSynchronizer);

        applicationService.registerDeactivateHook(appId, () -> {
            intentSynchronizer.removeIntentsByAppId(appId);
        });

        hostService.addListener(hostListener);
        interfaceService.addListener(interfaceListener);
        configService.addListener(configListener);

        setupConnectivity(false);

        log.info("Activated");
    }

    @Deactivate
    public void deactivate() {
        configService.removeListener(configListener);
        intentSynchronizer.removeIntentsByAppId(appId);
        log.info("Deactivated");
    }

    /**
     * Sets up connectivity for all VPLSs.
     *
     * @param isNetworkConfigEvent true if this function is triggered
     *                             by NetworkConfigEvent; false otherwise
     */
    private void setupConnectivity(boolean isNetworkConfigEvent) {
        SetMultimap<String, Interface> networkInterfaces =
                vplsConfigService.ifacesByVplsName();

        Set<String> vplsAffectedByApi =
                new HashSet<>(vplsConfigService.vplsAffectedByApi());

        if (isNetworkConfigEvent && vplsAffectedByApi.isEmpty()) {
            vplsAffectedByApi.addAll(vplsConfigService.vplsNamesOld());
        }

        networkInterfaces.asMap().forEach((vplsName, interfaces) -> {
            Set<Host> hosts = Sets.newHashSet();
            interfaces.forEach(intf -> {
                // Add hosts that belongs to the specific VPLS
                hostService.getConnectedHosts(intf.connectPoint())
                        .stream()
                        .filter(host -> host.vlan().equals(intf.vlan()))
                        .forEach(hosts::add);
            });

            EncapsulationType encap =
                    vplsConfigService.encap(vplsName);

            setupConnectivity(vplsName, interfaces, hosts, encap,
                              vplsAffectedByApi.contains(vplsName));
            vplsAffectedByApi.remove(vplsName);
        });

        if (!vplsAffectedByApi.isEmpty()) {
            for (String vplsName : vplsAffectedByApi) {
                withdrawIntents(vplsName, Lists.newArrayList());
            }
        }
    }

    /**
     * Sets up connectivity for specific VPLS.
     *
     * @param vplsName      the VPLS name
     * @param interfaces    the interfaces that belong to the VPLS
     * @param hosts         the hosts that belong to the VPLS
     * @param encap         the encapsulation type
     * @param affectedByApi true if this function is triggered from the APIs;
     *                      false otherwise
     */
    private void setupConnectivity(String vplsName,
                                   Collection<Interface> interfaces,
                                   Set<Host> hosts,
                                   EncapsulationType encap,
                                   boolean affectedByApi) {

        List<Intent> intents = Lists.newArrayList();
        List<Key> keys = Lists.newArrayList();
        Set<FilteredConnectPoint> fcPoints = buildFCPoints(interfaces);

        intents.addAll(buildBroadcastIntents(
                vplsName, fcPoints, encap, affectedByApi));
        intents.addAll(buildUnicastIntents(
                vplsName, hosts, fcPoints, encap, affectedByApi));

        if (affectedByApi) {
            intents.forEach(intent -> keys.add(intent.key()));
            withdrawIntents(vplsName, keys);
        }

        intentInstaller.submitIntents(intents);
    }

    /**
     * Withdraws intents belonging to a VPLS, given a VPLS name.
     *
     * @param vplsName the VPLS name
     * @param keys     the keys of the intents to be installed
     */
    private void withdrawIntents(String vplsName, List<Key> keys) {
        List<Intent> intents = Lists.newArrayList();

        intentInstaller.getIntentsFromVpls(vplsName)
                .forEach(intent -> {
                    if (!keys.contains(intent.key())) {
                        intents.add(intent);
                    }
                });

        intentInstaller.withdrawIntents(intents);
    }

    /**
     * Sets up broadcast intents between any given filtered connect point.
     *
     * @param vplsName      the VPLS name
     * @param fcPoints      the set of filtered connect points
     * @param encap         the encapsulation type
     * @param affectedByApi true if the function triggered from APIs;
     *                      false otherwise
     * @return the set of broadcast intents
     */
    private Set<Intent> buildBroadcastIntents(String vplsName,
                                              Set<FilteredConnectPoint> fcPoints,
                                              EncapsulationType encap,
                                              boolean affectedByApi) {
        Set<Intent> intents = Sets.newHashSet();
        fcPoints.forEach(point -> {
            Set<FilteredConnectPoint> otherPoints =
                    fcPoints.stream()
                            .filter(fcp -> !fcp.equals(point))
                            .collect(Collectors.toSet());

            Key brcKey = intentInstaller.buildKey(PREFIX_BROADCAST,
                                                  point.connectPoint(),
                                                  vplsName,
                                                  MacAddress.BROADCAST);

            if ((!intentInstaller.intentExists(brcKey) || affectedByApi)
                    && !otherPoints.isEmpty()) {
                intents.add(intentInstaller.buildBrcIntent(brcKey,
                                                           point,
                                                           otherPoints,
                                                           encap));
            }
        });

        return ImmutableSet.copyOf(intents);
    }

    /**
     * Sets up unicast intents between any given filtered connect point.
     *
     * @param vplsName      the VPLS name
     * @param hosts         the set of destination hosts
     * @param fcPoints      the set of filtered connect points
     * @param encap         the encapsulation type
     * @param affectedByApi true if the function triggered from APIs;
     *                      false otherwise
     * @return the set of unicast intents
     */
    private Set<Intent> buildUnicastIntents(String vplsName,
                                            Set<Host> hosts,
                                            Set<FilteredConnectPoint> fcPoints,
                                            EncapsulationType encap,
                                            boolean affectedByApi) {
        Set<Intent> intents = Sets.newHashSet();
        hosts.forEach(host -> {
            FilteredConnectPoint hostPoint = getHostPoint(host, fcPoints);

            if (hostPoint == null) {
                log.warn(HOST_FCP_NOT_FOUND, host);
                return;
            }

            Set<FilteredConnectPoint> otherPoints =
                    fcPoints.stream()
                            .filter(fcp -> !fcp.equals(hostPoint))
                            .collect(Collectors.toSet());

            Key uniKey = intentInstaller.buildKey(PREFIX_UNICAST,
                                                  host.location(),
                                                  vplsName,
                                                  host.mac());

            if ((!intentInstaller.intentExists(uniKey) || affectedByApi) &&
                    !otherPoints.isEmpty()) {
                intents.add(intentInstaller.buildUniIntent(uniKey,
                                                           otherPoints,
                                                           hostPoint,
                                                           host,
                                                           encap));
            }
        });

        return ImmutableSet.copyOf(intents);
    }

    /**
     * Returns the filtered connect point associated to a given host.
     *
     * @param host the target host
     * @param fcps the filtered connected points
     * @return null if not found; the filtered connect point otherwise
     */
    private FilteredConnectPoint getHostPoint(Host host,
                                              Set<FilteredConnectPoint> fcps) {
        return fcps.stream()
                .filter(fcp -> fcp.connectPoint().equals(host.location()))
                .filter(fcp -> {
                    VlanIdCriterion vlanCriterion =
                            (VlanIdCriterion) fcp.trafficSelector().
                                    getCriterion(Criterion.Type.VLAN_VID);
                    return vlanCriterion == null ||
                            vlanCriterion.vlanId().equals(host.vlan());
                })
                .findFirst()
                .orElse(null);
    }

    /**
     * Computes a set of filtered connect points from a list of given interfaces.
     *
     * @param interfaces the interfaces to compute
     * @return the set of filtered connect points
     */
    private Set<FilteredConnectPoint> buildFCPoints(Collection<Interface> interfaces) {
        // Build all filtered connected points in the VPLS
        return interfaces
                .stream()
                .map(intf -> {
                    TrafficSelector.Builder selectorBuilder =
                            DefaultTrafficSelector.builder();
                    if (!intf.vlan().equals(VlanId.NONE)) {
                        selectorBuilder.matchVlanId(intf.vlan());
                    }
                    return new FilteredConnectPoint(intf.connectPoint(),
                                                    selectorBuilder.build());
                })
                .collect(Collectors.toSet());
    }

    /**
     * Listener for host events.
     */
    private class InternalHostListener implements HostListener {
        @Override
        public void event(HostEvent event) {
            log.debug(HOST_EVENT, event);
            switch (event.type()) {
                case HOST_ADDED:
                case HOST_UPDATED:
                case HOST_REMOVED:
                    setupConnectivity(false);
                    break;

                default:
                    break;
            }
        }
    }

    /**
     * Listener for interface configuration events.
     */
    private class InternalInterfaceListener implements InterfaceListener {
        @Override
        public void event(InterfaceEvent event) {
            log.debug(INTF_CONF_EVENT, event);
            switch (event.type()) {
                case INTERFACE_ADDED:
                case INTERFACE_UPDATED:
                case INTERFACE_REMOVED:
                    setupConnectivity(false);
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * Listener for VPLS configuration events.
     */
    private class InternalNetworkConfigListener implements NetworkConfigListener {
        @Override
        public void event(NetworkConfigEvent event) {
            if (event.configClass() == VplsConfigService.CONFIG_CLASS) {
                log.debug(NET_CONF_EVENT, event.configClass());
                switch (event.type()) {
                    case CONFIG_ADDED:
                    case CONFIG_UPDATED:
                    case CONFIG_REMOVED:
                        setupConnectivity(true);
                        break;
                    default:
                        break;
                }
            }
        }
    }
}
