/*
 * 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.imr;

import com.google.common.collect.ImmutableSet;
import org.apache.commons.lang3.tuple.Pair;
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.util.KryoNamespace;
import org.onosproject.core.ApplicationId;
import org.onosproject.imr.data.Path;
import org.onosproject.imr.data.Route;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.ElementId;
import org.onosproject.net.FilteredConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleListener;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intent.ConnectivityIntent;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentListener;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.LinkCollectionIntent;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.statistic.FlowStatisticStore;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.DistributedSet;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

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

/**
 * Manager of Intent Monitor and Reroute.
 */
@Component(immediate = true)
@Service
public class IntentMonitorAndRerouteManager implements IntentMonitorAndRerouteService {

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

    private ConsistentMap<ApplicationId, Map<Key, ConnectivityIntent>> monitoredIntentsDistr;
    private Map<ApplicationId, Map<Key, ConnectivityIntent>> monitoredIntents;

    private DistributedSet<Key> toBeMonitoredIntents;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowRuleService flowRuleService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LinkService linkService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowStatisticStore statsStore;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected StorageService storageService;

    private InternalIntentListener intentListener = new InternalIntentListener();

    private InternalFlowRuleListener flowRuleListener = new InternalFlowRuleListener();

    @Activate
    protected void activate() {
        intentService.addListener(intentListener);
        flowRuleService.addListener(flowRuleListener);

        monitoredIntentsDistr = storageService
                .<ApplicationId, Map<Key, ConnectivityIntent>>consistentMapBuilder()
                .withSerializer(Serializer.using(KryoNamespaces.API))
                .withName("IMR-monitoredIntents")
                .build();
        monitoredIntents = monitoredIntentsDistr.asJavaMap();

        toBeMonitoredIntents = storageService.<Key>setBuilder()
                .withSerializer(Serializer.using(
                        new KryoNamespace.Builder()
                                .register(KryoNamespaces.API)
                                .register(Key.class)
                                .build()))
                .withName("IMR-toMonitorIntents")
                .build()
                .asDistributedSet();
        log.info("IntentMonitorAndReroute activated");
    }

    @Deactivate
    protected void deactivate() {
        intentService.removeListener(intentListener);
        flowRuleService.removeListener(flowRuleListener);
        monitoredIntents
                .forEach(((applicationId, keyConnectivityIntentMap) ->
                        keyConnectivityIntentMap.keySet()
                                .forEach(this::removeIntent)));
        log.info("IntentMonitorAndReroute deactivated");
    }


    private synchronized void storeMonitoredIntent(ConnectivityIntent intent) {
        log.debug("Store Monitored Intent {}", intent.key());
        Map<Key, ConnectivityIntent> temp = monitoredIntents.getOrDefault(intent.appId(), new ConcurrentHashMap<>());
        temp.put(intent.key(), intent);
        monitoredIntents.put(intent.appId(), temp);
    }

    @Override
    public synchronized boolean startMonitorIntent(Key intentKey) {
        checkNotNull(intentKey, "Intent Key must not be null");
        log.debug("Start Monitor Intent: {}", intentKey.toString());
        toBeMonitoredIntents.add(intentKey);

        //Check if the requested intent is already present in the intent manager
        Intent installedIntent = intentService.getIntent(intentKey);
        if (!allowedIntent(installedIntent)) {
            return false;
        }
        //Check if the intent that is present in the intent subsystem is already installed
        if (intentService.getIntentState(intentKey) == IntentState.INSTALLED) {
            storeMonitoredIntent((ConnectivityIntent) installedIntent);
        }
        return true;
    }


    /**
     * Returns whether the intent can be monitored or not.
     * @param intent The intent you want to check if it is allowed to be monitored.
     * @return true if the intent's type is of one of the allowed types
     * ({@link LinkCollectionIntent}, {@link PointToPointIntent}).
     */
    public boolean allowedIntent(Intent intent) {
        return intent instanceof LinkCollectionIntent || intent instanceof PointToPointIntent;
    }

    @Override
    public synchronized boolean stopMonitorIntent(Key intentKey) {
        checkNotNull(intentKey, "Intent key must not be null");
        log.debug("Stop Monitor Intent: ", intentKey.toString());
        if (!toBeMonitoredIntents.contains(intentKey)) {
            return false;
        }
        removeIntent(intentKey);
        toBeMonitoredIntents.remove(intentKey);
        return true;
    }

    /**
     * Removes the intent from the internal structure.
     * @param intentKey Key of the intent to be removed.
     * @return true if the intent is found and removed, false otherwise.
     */
    private synchronized boolean removeIntent(Key intentKey) {
        for (Map.Entry<ApplicationId, Map<Key, ConnectivityIntent>> appIntents
                : monitoredIntents.entrySet()) {
            if (appIntents.getValue().containsKey(intentKey)) {
                appIntents.getValue().remove(intentKey);
                //TODO: check if it works without reputting the map
                flushIntentStatStore(intentKey);
                monitoredIntents.put(appIntents.getKey(), appIntents.getValue());
                if (appIntents.getValue().isEmpty()) {
                    monitoredIntents.remove(appIntents.getKey());
                }
                return true;
            }
        }
        return false;
    }

    /**
     * Flushes the statistics (from the statistics store) of an intent.
     * @param intentKey Key of the intent which statistics has to be cleaned.
     */
    private synchronized void flushIntentStatStore(Key intentKey) {
        checkNotNull(intentKey);
        //Remove all the flow rule on the stats store related to the passed intentKey
        intentService.getInstallableIntents(intentKey)
                .stream()
                .map(intent -> (FlowRuleIntent) intent)
                .forEach(intent -> intent.flowRules()
                        .forEach(flowRule -> statsStore.removeFlowStatistic(flowRule))
                );
    }


    /**
     * Generates a new {@Link LinkCollectionIntent} applying the new path.
     * @param links List of links of the new path.
     * @param intentKey Key of the intent you want to re-route.
     * @param appId Application id that submits initially the intent.
     * @return The new intent, if not possibile it will return the old intent already installed.
     */
    private ConnectivityIntent generateLinkCollectionIntent(
            List<Link> links,
            Key intentKey,
            ApplicationId appId) {
        checkNotNull(links);
        checkNotNull(appId);

        // Gets the oldIntent already installed
        ConnectivityIntent oldIntent = monitoredIntents.get(appId).get(intentKey);

        //Flush the statistics of the currently installed intent
        flushIntentStatStore(intentKey);

        //get the connect point of the old intent
        // Left element of the Pair is the ingress, right one is the egress
        Pair<Set<FilteredConnectPoint>, Set<FilteredConnectPoint>> cpPair = extractEndConnectPoints(oldIntent);
        if (cpPair == null) {
            return oldIntent;
        }

        // Now generate the new intent
        LinkCollectionIntent newIntent = LinkCollectionIntent.builder()
                .appId(oldIntent.appId())
                .key(intentKey)
                .selector(oldIntent.selector())
                .filteredIngressPoints(ImmutableSet.copyOf(cpPair.getLeft()))
                .filteredEgressPoints(ImmutableSet.copyOf(cpPair.getRight()))
                .treatment(oldIntent.treatment())
                .priority(oldIntent.priority())
                .constraints(oldIntent.constraints())
                .links(ImmutableSet.copyOf(links))
                //TODO: is there a way to get from the old intent?
                .applyTreatmentOnEgress(true)
                .build();

        return newIntent;
    }

    @Override
    public boolean applyPath(Route route) {
        checkNotNull(route, "Route to apply must be not null");
        checkNotNull(route.appId(), "Application id must be not null");
        checkNotNull(route.key(), "Intent key to apply must be not null");
        checkNotNull(route.paths(), "New path must be not null");
        checkArgument(route.paths().size() >= 1);

        ApplicationId appId = route.appId();
        Key key = route.key();

        // check if the app and the intent key are monitored
        if (!monitoredIntents.containsKey(appId)) {
            return false;
        }
        if (!monitoredIntents.get(appId).containsKey(key)) {
            return false;
        }

        // TODO: now we manage only the unsplittable routing
        Path currentPath = route.paths()
                .stream()
                .max(Comparator.comparing(Path::weight))
                .get();

        // Check if the last and first element of the path are HostId
        // in this case remove them from the list
        if (currentPath.path().get(0) instanceof HostId) {
            currentPath.path().remove(0);
        }
        if (currentPath.path().get(currentPath.path().size() - 1) instanceof HostId) {
            currentPath.path().remove(currentPath.path().size() - 1);
        }

        List<Link> links = createPathFromDeviceList(currentPath.path());

        // Generate the new Link collection intent, if not possible it will return the old intent
        ConnectivityIntent intent = generateLinkCollectionIntent(links, key, appId);
        storeMonitoredIntent(intent);
        intentService.submit(intent);
        return true;
    }

    @Override
    public Map<ApplicationId, Map<Key, List<FlowEntry>>> getStats() {
        //TODO: check if there is a better way to get the statistics
        Map<ApplicationId, Map<Key, List<FlowEntry>>> currentStatistics = new HashMap<>();
        monitoredIntents.forEach((appId, mapIntentKey) ->
                                         currentStatistics.putAll(getStats(appId))
        );
        return currentStatistics;
    }

    @Override
    public Map<ApplicationId, Map<Key, List<FlowEntry>>> getStats(ApplicationId appId) {
        checkNotNull(appId);

        //TODO: is there a better way to get statistics?
        Map<ApplicationId, Map<Key, List<FlowEntry>>> currentStatistics = new HashMap<>();
        currentStatistics.put(appId, new HashMap<>());
        if (monitoredIntents.containsKey(appId)) {
            Set<Key> keySet = monitoredIntents.get(appId).keySet();
            for (Key intentKey : keySet) {

                List<FlowEntry> flowEntries = getStats(intentKey);
                currentStatistics.get(appId).put(intentKey, flowEntries);
            }
        }
        return currentStatistics;
    }

    @Override
    public Map<ApplicationId, Map<Key, List<FlowEntry>>> getStats(ApplicationId appId, Key intentKey) {
        checkNotNull(appId);
        checkNotNull(intentKey);
        checkArgument(monitoredIntents.containsKey(appId));
        checkArgument(monitoredIntents.get(appId).containsKey(intentKey));

        Map<ApplicationId, Map<Key, List<FlowEntry>>> currentStatistics = new HashMap<>();
        currentStatistics.put(appId, new HashMap<>());
        List<FlowEntry> flowEntries = getStats(intentKey);
        currentStatistics.get(appId).put(intentKey, flowEntries);
        return currentStatistics;
    }

    /**
     * Returns the list of flow entries of a particular intent.
     * @param intentKey
     * @return List of the flow entries of the specified intent,
     * it contains all the statistics of that intent.
     */
    private List<FlowEntry> getStats(Key intentKey) {
        List<FlowEntry> currentStatistics = new LinkedList<>();
        intentService.getInstallableIntents(intentKey)
                .forEach(intent -> ((FlowRuleIntent) intent).flowRules()
                         .forEach(flowRule -> {
                             ConnectPoint cp = buildConnectPoint(flowRule);
                             currentStatistics.addAll(getStats(cp, flowRule));
                         })
                );
        return currentStatistics;
    }

    /**
     * Returns a list of flow entry related to the connect point and flow rule passed.
     * @param cp ConnectPoint we want to retrieve the flow entry from.
     * @param flowRule FlowRule.
     * @return List of flow entries.
     */
    private List<FlowEntry> getStats(ConnectPoint cp, FlowRule flowRule) {
        return statsStore.getCurrentFlowStatistic(cp)
                .stream()
                .filter(flowEntry -> flowEntry
                        .id()
                        .equals(flowRule.id()))
                .collect(Collectors.toList());
    }

    /**
     * Returns a list of links starting from a list of devices.
     * @param deviceList List of devices.
     * @return A path in terms of list of links.
     */
    private List<Link> createPathFromDeviceList(List<ElementId> deviceList) {
        List<Link> path = new ArrayList<>();
        if (deviceList.size() == 1) {
            return path;
        }

        // Left element represents the input and right the output
        List<Pair<DeviceId, DeviceId>> devicePairs = IntStream.
                range(0, deviceList.size() - 1)
                .mapToObj(i -> Pair.of((DeviceId) deviceList.get(i), (DeviceId) deviceList.get(i + 1)))
                .collect(Collectors.toList());

        devicePairs.forEach(pair -> {
            //TODO use GetPath pair by pair?
            // The common Link between DevEgress and DevIngress is the intersection of their links
            Set<Link> commonLinks = new HashSet<>(linkService.getDeviceEgressLinks(pair.getLeft()));
            commonLinks.retainAll(linkService.getDeviceIngressLinks(pair.getRight()));
            if (commonLinks.size() == 0) {
                log.error("No link found between node {} and node {}!",
                          pair.getLeft(), pair.getRight());
            } else if (commonLinks.size() == 1) {
                path.add(commonLinks.iterator().next());
            } else {
                //TODO select the one with more bandwidth?
                log.warn("{} links found between node {} and node {}: taking the first one!",
                         commonLinks.size(), pair.getLeft(), pair.getRight());
                path.add(commonLinks.iterator().next());
            }
        });

        return path;
    }

    @Override
    public Map<ApplicationId, Map<Key, Pair<Set<ElementId>, Set<ElementId>>>> getMonitoredIntents() {
        Map<ApplicationId, Map<Key, Pair<Set<ElementId>, Set<ElementId>>>> currentMonitoredIntents
                = new ConcurrentHashMap<>();
        monitoredIntents.forEach((appId, appIntents) -> {
            currentMonitoredIntents.put(appId, new ConcurrentHashMap<>());
            appIntents.forEach((intentKey, intent) -> {
                Pair<Set<ElementId>, Set<ElementId>> endPair = extractEndPoints(intent);
                if (endPair != null) {
                    currentMonitoredIntents.get(appId).put(intentKey, endPair);
                }
            });
        });
        return currentMonitoredIntents;
    }

    @Override
    public Map<ApplicationId, Map<Key, Pair<Set<ElementId>, Set<ElementId>>>> getMonitoredIntents(
            ApplicationId appId) {
        Map<ApplicationId, Map<Key, Pair<Set<ElementId>, Set<ElementId>>>> currentMonitoredIntents
                = new ConcurrentHashMap<>();
        currentMonitoredIntents.put(appId, new ConcurrentHashMap<>());
        if (monitoredIntents.containsKey(appId)) {
            monitoredIntents.get(appId).forEach((intentKey, intent) -> {
                Pair<Set<ElementId>, Set<ElementId>> endPair = extractEndPoints(intent);
                if (endPair != null) {
                    currentMonitoredIntents.get(appId).put(intentKey, endPair);
                }
            });
        }
        return currentMonitoredIntents;
    }

    private Set<ElementId> connectedElements(Set<FilteredConnectPoint> cpSet) {
        Set<ElementId> connectedElem = new HashSet<>();
        cpSet.forEach(
            fcp -> {
                Set<Host> connectedHosts = hostService.getConnectedHosts(fcp.connectPoint());
                if (connectedHosts.size() == 0) {
                    // In this case the end point is an ELEMENT without host connected
                    connectedElem.add(fcp.connectPoint().elementId());
                } else {
                    // In this case we can have a set of hosts connected to that endpoint
                    connectedElem.addAll(connectedHosts.stream().map(Host::id)
                                   .collect(Collectors.toSet()));
                }
            }
        );
        return connectedElem;
    }

    /**
     * Extracts the endpoint from an intent.
     * @param intent
     * @return {@link Pair} containing in the Left element the set of input {@link ElementId},
     * in the Right element the set of output {@link ElementId}.
     */
    private Pair<Set<ElementId>, Set<ElementId>> extractEndPoints(Intent intent) {
        checkNotNull(intent, "intent must not be null");
        Pair<Set<FilteredConnectPoint>, Set<FilteredConnectPoint>> cpPair;
        cpPair = extractEndConnectPoints(intent);
        if (cpPair == null) {
            return null;
        }
        return Pair.of(connectedElements(cpPair.getLeft()), connectedElements(cpPair.getRight()));
    }

    /**
     * Returns the end connect points of an intent.
     * @param intent
     * @return {@link Pair} containing in the Left element the input end connect points,
     * in the Right element the output end connect points.
     */
    private Pair<Set<FilteredConnectPoint>, Set<FilteredConnectPoint>> extractEndConnectPoints(Intent intent) {
        checkNotNull(intent, "intent must not be null");

        Set<FilteredConnectPoint> inSet = new HashSet<>();
        Set<FilteredConnectPoint> outSet = new HashSet<>();
        if (intent instanceof PointToPointIntent) {
            inSet.add(((PointToPointIntent) intent).filteredIngressPoint());
            outSet.add(((PointToPointIntent) intent).filteredEgressPoint());
        } else if (intent instanceof LinkCollectionIntent) {
            inSet.addAll(((LinkCollectionIntent) intent).filteredIngressPoints());
            outSet.addAll(((LinkCollectionIntent) intent).filteredEgressPoints());
        }
        return Pair.of(inSet, outSet);
    }

    /**
     * Returns the connect point related to the output port of the rule.
     * @param rule
     * @return
     */
    private ConnectPoint buildConnectPoint(FlowRule rule) {
        PortNumber port = getOutput(rule);

        if (port == null) {
            return null;
        }
        return new ConnectPoint(rule.deviceId(), port);
    }

    /**
     * Returns the output port related to the rule.
     * @param rule
     * @return
     */
    private PortNumber getOutput(FlowRule rule) {
        for (Instruction i : rule.treatment().allInstructions()) {
            if (i.type() == Instruction.Type.OUTPUT) {
                Instructions.OutputInstruction out = (Instructions.OutputInstruction) i;
                return out.port();
            }
        }
        return null;
    }


    private class InternalIntentListener implements IntentListener {

        @Override
        public void event(IntentEvent event) {
            // It receives only events related to ConnectivityIntent to be monitored
            Key intentKey = event.subject().key();
            switch (event.type()) {
                case INSTALLED:
                    // When an intent is installed and it need to be monitored
                    // it will pass from the "toBeMonitored" state to the "monitored" state
                    log.info("Monitored intent INSTALLED");
                    storeMonitoredIntent((ConnectivityIntent) event.subject());
                    break;

                case WITHDRAWN:
                    // When an intent is withdrawn
                    // it will go back from the "monitored" state to the "toBeMonitored"
                    log.info("Monitored intent WITHDWRAWN");
                    removeIntent(intentKey);
                    break;

                case FAILED:
                    log.warn("FAILED event not handled");
                    break;
                default:
                    log.warn("Unknown intent event");
            }
        }

        @Override
        public boolean isRelevant(IntentEvent event) {
            /*
             * Check if the Intent event is relevant.
             * An intent event is relevant if it is of one of the allowed types
             * and if it is one of the monitored ones.
             */
            Key intentKey = event.subject().key();
            return allowedIntent(event.subject())
                    && toBeMonitoredIntents.contains(intentKey);
        }
    }

    private class InternalFlowRuleListener implements FlowRuleListener {
        @Override
        public void event(FlowRuleEvent event) {
            FlowRule rule = event.subject();
            switch (event.type()) {
                case RULE_ADDED:
                case RULE_UPDATED:
                    // In case of rule update, flow statistics are updated
                    if (rule instanceof FlowEntry) {
                        statsStore.updateFlowStatistic((FlowEntry) rule);
                    }
                    break;
                case RULE_REMOVED:
                    // In case of rule removal, flow statistics are removed from the store
                    log.info("Rule removed: {}", rule.id());
                    statsStore.removeFlowStatistic(rule);
                    break;
                default:
                    log.warn("Unknown flow rule event");
            }
        }

        @Override
        public boolean isRelevant(FlowRuleEvent event) {
            /*
            *  Check if the rule event is relevant and it needs to be managed
             * A Rule event is relevant if the flow rule it refers to is
             * part of one of the monitored intents
             */
            FlowRule rule = event.subject();
            for (Map.Entry<ApplicationId, Map<Key, ConnectivityIntent>> entry : monitoredIntents.entrySet()) {
                for (Key key : entry.getValue().keySet()) {
                    List<Intent> ints =  intentService.getInstallableIntents(key);
                    for (Intent i : ints) {
                        if (i instanceof FlowRuleIntent
                                && ((FlowRuleIntent) i).flowRules().contains(rule)) {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
    }
}