/*
 * 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.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.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.onosproject.simplefabric.api.L2Network;
import org.onosproject.simplefabric.api.SimpleFabricEvent;
import org.onosproject.simplefabric.api.SimpleFabricListener;
import org.onosproject.simplefabric.api.SimpleFabricService;
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_UNARY)
    protected CoreService coreService;

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

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    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;
            }
        }
    }

}
