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

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.intf.Interface;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.EncapsulationType;
import org.onosproject.net.FilteredConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.ResourceGroup;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
import org.onosproject.net.intent.constraint.EncapsulationConstraint;
import org.onosproject.net.intent.constraint.PartialFailureConstraint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * An implementation of L2NetworkOperationService.
 * Handles the execution order of the L2 Network operations generated by the
 * application.
 */
@Component(immediate = true, enabled = false)
public class SimpleFabricL2Forward {

    public static final String BROADCAST = "BCAST";
    public static final String UNICAST = "UNI";

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

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

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

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected SimpleFabricService simpleFabric;

    public static final ImmutableList<Constraint> L2NETWORK_CONSTRAINTS =
            ImmutableList.of(new PartialFailureConstraint());

    private Map<Key, SinglePointToMultiPointIntent> bctIntentsMap = Maps.newConcurrentMap();
    private Map<Key, MultiPointToSinglePointIntent> uniIntentsMap = Maps.newConcurrentMap();
    private Set<Key> toBePurgedIntentKeys = new HashSet<>();

    private final InternalSimpleFabricListener simpleFabricListener = new InternalSimpleFabricListener();

    @Activate
    public void activate() {
        l2ForwardAppId = coreService.registerApplication(simpleFabric.L2FORWARD_APP_ID);
        log.info("simple fabric l2 forwaring starting with l2net app id {}", l2ForwardAppId.toString());

        simpleFabric.addListener(simpleFabricListener);

        refresh();
        checkIntentsPurge();

        log.info("simple fabric l2forward started");
    }

    @Deactivate
    public void deactivate() {
        log.info("simple fabric l2forward stopping");

        simpleFabric.removeListener(simpleFabricListener);

        for (Intent intent : bctIntentsMap.values()) {
            intentService.withdraw(intent);
            toBePurgedIntentKeys.add(intent.key());
        }
        for (Intent intent : uniIntentsMap.values()) {
            intentService.withdraw(intent);
            toBePurgedIntentKeys.add(intent.key());
        }
        for (Key key : toBePurgedIntentKeys) {
            Intent intentToPurge = intentService.getIntent(key);
            if (intentToPurge != null) {
                intentService.purge(intentToPurge);
            }
        }

        // do not set clear for switch compatibility
        //bctIntentsMap.clear();
        //uniIntentsMap.clear();

        log.info("simple fabric l2forward stopped");
    }

    private void refresh() {
        log.debug("simple fabric l2forward refresh");

        Map<Key, SinglePointToMultiPointIntent> newBctIntentsMap = Maps.newConcurrentMap();
        Map<Key, MultiPointToSinglePointIntent> newUniIntentsMap = Maps.newConcurrentMap();

        for (L2Network l2Network : simpleFabric.getL2Networks()) {
            // scans all l2network regardless of dirty flag
            // if l2Network.l2Forward == false or number of interfaces() < 2, no Intents generated
            for (SinglePointToMultiPointIntent intent : buildBrcIntents(l2Network)) {
                newBctIntentsMap.put(intent.key(), intent);
            }
            for (MultiPointToSinglePointIntent intent : buildUniIntents(l2Network, hostsFromL2Network(l2Network))) {
                newUniIntentsMap.put(intent.key(), intent);
            }
            if (l2Network.dirty()) {
                l2Network.setDirty(false);
            }
        }

        boolean bctUpdated = false;
        for (SinglePointToMultiPointIntent intent : bctIntentsMap.values()) {
            SinglePointToMultiPointIntent newIntent = newBctIntentsMap.get(intent.key());
            if (newIntent == null) {
                log.info("simple fabric l2forward withdraw broadcast intent: {}", intent.key().toString());
                toBePurgedIntentKeys.add(intent.key());
                intentService.withdraw(intent);
                bctUpdated = true;
            }
        }
        for (SinglePointToMultiPointIntent intent : newBctIntentsMap.values()) {
            SinglePointToMultiPointIntent oldIntent = bctIntentsMap.get(intent.key());
            if (oldIntent == null ||
                    !oldIntent.filteredEgressPoints().equals(intent.filteredEgressPoints()) ||
                    !oldIntent.filteredIngressPoint().equals(intent.filteredIngressPoint()) ||
                    !oldIntent.selector().equals(intent.selector()) ||
                    !oldIntent.treatment().equals(intent.treatment()) ||
                    !oldIntent.constraints().equals(intent.constraints())) {
                log.info("simple fabric l2forward submit broadcast intent: {}", intent.key().toString());
                toBePurgedIntentKeys.remove(intent.key());
                intentService.submit(intent);
                bctUpdated = true;
            }
        }

        boolean uniUpdated = false;
        for (MultiPointToSinglePointIntent intent : uniIntentsMap.values()) {
            MultiPointToSinglePointIntent newIntent = newUniIntentsMap.get(intent.key());
            if (newIntent == null) {
                log.info("simple fabric l2forward withdraw unicast intent: {}", intent.key().toString());
                toBePurgedIntentKeys.add(intent.key());
                intentService.withdraw(intent);
                uniUpdated = true;
            }
        }
        for (MultiPointToSinglePointIntent intent : newUniIntentsMap.values()) {
            MultiPointToSinglePointIntent oldIntent = uniIntentsMap.get(intent.key());
            if (oldIntent == null ||
                    !oldIntent.filteredEgressPoint().equals(intent.filteredEgressPoint()) ||
                    !oldIntent.filteredIngressPoints().equals(intent.filteredIngressPoints()) ||
                    !oldIntent.selector().equals(intent.selector()) ||
                    !oldIntent.treatment().equals(intent.treatment()) ||
                    !oldIntent.constraints().equals(intent.constraints())) {
                log.info("simple fabric l2forward submit unicast intent: {}", intent.key().toString());
                toBePurgedIntentKeys.remove(intent.key());
                intentService.submit(intent);
                uniUpdated = true;
            }
        }

        if (bctUpdated) {
            bctIntentsMap = newBctIntentsMap;
        }
        if (uniUpdated) {
            uniIntentsMap = newUniIntentsMap;
        }
    }

    private void checkIntentsPurge() {
        // check intents to be purge
        if (!toBePurgedIntentKeys.isEmpty()) {
            Set<Key> purgedKeys = new HashSet<>();
            for (Key key : toBePurgedIntentKeys) {
                Intent intentToPurge = intentService.getIntent(key);
                if (intentToPurge == null) {
                    log.info("simple fabric l2forward purged intent: key={}", key.toString());
                    purgedKeys.add(key);
                } else {
                    switch (intentService.getIntentState(key)) {
                    case FAILED:
                    case WITHDRAWN:
                        log.info("simple fabric l2forward try to purge intent: key={}", key.toString());
                        intentService.purge(intentToPurge);
                        break;
                    case INSTALL_REQ:
                    case INSTALLED:
                    case INSTALLING:
                    case RECOMPILING:
                    case COMPILING:
                        log.warn("simple fabric l2forward withdraw intent to purge: key={}", key);
                        intentService.withdraw(intentToPurge);
                        break;
                    case WITHDRAW_REQ:
                    case WITHDRAWING:
                    case PURGE_REQ:
                    case CORRUPT:
                    default:
                        // no action
                        break;
                    }
                }
            }
            toBePurgedIntentKeys.removeAll(purgedKeys);
        }
    }

    // Generates Unicast Intents and broadcast Intents for the L2 Network.

    private Set<Intent> generateL2NetworkIntents(L2Network l2Network) {
        return new ImmutableSet.Builder<Intent>()
                .addAll(buildBrcIntents(l2Network))
                .addAll(buildUniIntents(l2Network, hostsFromL2Network(l2Network)))
                .build();
    }

    // Build Boadcast Intents for a L2 Network.
    private Set<SinglePointToMultiPointIntent> buildBrcIntents(L2Network l2Network) {
        Set<Interface> interfaces = l2Network.interfaces();
        if (interfaces.size() < 2 || !l2Network.l2Forward() || !l2Network.l2Broadcast()) {
            return ImmutableSet.of();
        }
        Set<SinglePointToMultiPointIntent> brcIntents = Sets.newHashSet();
        ResourceGroup resourceGroup = ResourceGroup.of(l2Network.name());

        // Generates broadcast Intents from any network interface to other
        // network interface from the L2 Network.
        interfaces
            .forEach(src -> {
            FilteredConnectPoint srcFcp = buildFilteredConnectedPoint(src);
            Set<FilteredConnectPoint> dstFcps = interfaces.stream()
                    .filter(iface -> !iface.equals(src))
                    .map(this::buildFilteredConnectedPoint)
                    .collect(Collectors.toSet());
            Key key = buildKey(l2Network.name(), "BCAST", srcFcp.connectPoint(), MacAddress.BROADCAST);
            TrafficSelector selector = DefaultTrafficSelector.builder()
                    .matchEthDst(MacAddress.BROADCAST)
                    .build();
            SinglePointToMultiPointIntent.Builder intentBuilder = SinglePointToMultiPointIntent.builder()
                    .appId(l2ForwardAppId)
                    .key(key)
                    .selector(selector)
                    .filteredIngressPoint(srcFcp)
                    .filteredEgressPoints(dstFcps)
                    .constraints(buildConstraints(L2NETWORK_CONSTRAINTS, l2Network.encapsulation()))
                    .priority(SimpleFabricService.PRI_L2NETWORK_BROADCAST)
                    .resourceGroup(resourceGroup);
            brcIntents.add(intentBuilder.build());
        });
        return brcIntents;
    }

    // Builds unicast Intents for a L2 Network.
    private Set<MultiPointToSinglePointIntent> buildUniIntents(L2Network l2Network, Set<Host> hosts) {
        Set<Interface> interfaces = l2Network.interfaces();
        if (!l2Network.l2Forward() || interfaces.size() < 2) {
            return ImmutableSet.of();
        }
        Set<MultiPointToSinglePointIntent> uniIntents = Sets.newHashSet();
        ResourceGroup resourceGroup = ResourceGroup.of(l2Network.name());
        hosts.forEach(host -> {
            FilteredConnectPoint hostFcp = buildFilteredConnectedPoint(host);
            Set<FilteredConnectPoint> srcFcps = interfaces.stream()
                    .map(this::buildFilteredConnectedPoint)
                    .filter(fcp -> !fcp.equals(hostFcp))
                    .collect(Collectors.toSet());
            Key key = buildKey(l2Network.name(), "UNI", hostFcp.connectPoint(), host.mac());
            TrafficSelector selector = DefaultTrafficSelector.builder()
                    .matchEthDst(host.mac()).build();
            MultiPointToSinglePointIntent.Builder intentBuilder = MultiPointToSinglePointIntent.builder()
                    .appId(l2ForwardAppId)
                    .key(key)
                    .selector(selector)
                    .filteredIngressPoints(srcFcps)
                    .filteredEgressPoint(hostFcp)
                    .constraints(buildConstraints(L2NETWORK_CONSTRAINTS, l2Network.encapsulation()))
                    .priority(SimpleFabricService.PRI_L2NETWORK_UNICAST)
                    .resourceGroup(resourceGroup);
            uniIntents.add(intentBuilder.build());
        });

        return uniIntents;
    }

    // Intent generate utilities

    private Set<Host> hostsFromL2Network(L2Network l2Network) {
        Set<Interface> interfaces = l2Network.interfaces();
        return interfaces.stream()
                .map(this::hostsFromInterface)
                .flatMap(Collection::stream)
                .collect(Collectors.toSet());
    }

    private Set<Host> hostsFromInterface(Interface iface) {
        return hostService.getConnectedHosts(iface.connectPoint())
                .stream()
                .filter(host -> host.vlan().equals(iface.vlan()))
                .collect(Collectors.toSet());
    }

    private Key buildKey(String l2NetworkName, String type, ConnectPoint cPoint, MacAddress dstMac) {
        return Key.of(l2NetworkName + "-" + type + "-" + cPoint.toString() + "-" + dstMac, l2ForwardAppId);
    }

    private List<Constraint> buildConstraints(List<Constraint> constraints, EncapsulationType encapsulation) {
        if (!encapsulation.equals(EncapsulationType.NONE)) {
            List<Constraint> newConstraints = new ArrayList<>(constraints);
            constraints.stream()
                .filter(c -> c instanceof EncapsulationConstraint)
                .forEach(newConstraints::remove);
            newConstraints.add(new EncapsulationConstraint(encapsulation));
            return ImmutableList.copyOf(newConstraints);
        }
        return constraints;
    }

    private FilteredConnectPoint buildFilteredConnectedPoint(Interface iface) {
        Objects.requireNonNull(iface);
        TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();

        if (iface.vlan() != null && !iface.vlan().equals(VlanId.NONE)) {
            trafficSelector.matchVlanId(iface.vlan());
        }
        return new FilteredConnectPoint(iface.connectPoint(), trafficSelector.build());
    }

    protected FilteredConnectPoint buildFilteredConnectedPoint(Host host) {
        Objects.requireNonNull(host);
        TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();

        if (host.vlan() != null && !host.vlan().equals(VlanId.NONE)) {
            trafficSelector.matchVlanId(host.vlan());
        }
        return new FilteredConnectPoint(host.location(), trafficSelector.build());
    }

    // Dump command handler
    private void dump(String subject, PrintStream out) {
        if ("intents".equals(subject)) {
            out.println("L2Forward Broadcast Intents:\n");
            for (SinglePointToMultiPointIntent intent: bctIntentsMap.values()) {
                out.println("    " + intent.key().toString()
                          + ": " + intent.selector().criteria()
                          + ", [" + intent.filteredIngressPoint().connectPoint()
                          + "] -> " + intent.filteredEgressPoints().stream()
                                      .map(FilteredConnectPoint::connectPoint).collect(Collectors.toSet()));
            }
            out.println("");
            out.println("L2Forward Unicast Intents:\n");
            for (MultiPointToSinglePointIntent intent: uniIntentsMap.values()) {
                out.println("    " + intent.key().toString()
                          + ": " + intent.selector().criteria()
                          + ", [" + intent.filteredIngressPoints().stream()
                                    .map(FilteredConnectPoint::connectPoint).collect(Collectors.toSet())
                          + "] -> " + intent.filteredEgressPoint().connectPoint());
            }
            out.println("");
            out.println("L2Forward Intents to Be Purged:\n");
            for (Key key: toBePurgedIntentKeys) {
                out.println("    " + key.toString());
            }
            out.println("");
        }
    }

    // Listener
    private class InternalSimpleFabricListener implements SimpleFabricListener {
        @Override
        public void event(SimpleFabricEvent event) {
            switch (event.type()) {
            case SIMPLE_FABRIC_UPDATED:
                refresh();
                checkIntentsPurge();
                break;
            case SIMPLE_FABRIC_IDLE:
                refresh();
                checkIntentsPurge();
                break;
            case SIMPLE_FABRIC_DUMP:
                dump(event.subject(), event.out());
                break;
            default:
                // NOTE: nothing to do on SIMPLE_FABRIC_FLUSH
                break;
            }
        }
    }

}
