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

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.ElementId;
import org.onosproject.net.HostId;
import org.onosproject.net.Link;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.OpticalConnectivityIntent;
import org.onosproject.net.intent.ProtectionEndpointIntent;
import org.onosproject.net.link.LinkService;
import org.onosproject.ui.impl.topo.util.ServicesBundle;
import org.onosproject.ui.impl.topo.util.TrafficLink;
import org.onosproject.ui.impl.topo.util.TrafficLink.StatsType;
import org.onosproject.ui.impl.topo.util.TrafficLinkMap;
import org.onosproject.ui.topo.AbstractTopoMonitor;
import org.onosproject.ui.topo.DeviceHighlight;
import org.onosproject.ui.topo.Highlights;
import org.onosproject.ui.topo.HostHighlight;
import org.onosproject.ui.topo.LinkHighlight.Flavor;
import org.onosproject.ui.topo.Mod;
import org.onosproject.ui.topo.NodeHighlight;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.stream.Collectors;

import static org.onosproject.net.MarkerResource.marker;
import static org.onosproject.ui.impl.ProtectedIntentMonitor.ProtectedMode.IDLE;
import static org.onosproject.ui.impl.ProtectedIntentMonitor.ProtectedMode.SELECTED_INTENT;

/**
 * Encapsulates the behavior of monitoring protected intents.
 */
//TODO refactor duplicated methods from here and the TrafficMonitor to AbstractTopoMonitor
public class ProtectedIntentMonitor extends AbstractTopoMonitor {

    private static final Logger log =
            LoggerFactory.getLogger(ProtectedIntentMonitor.class);
    private static final String PRIMARY_PATH_TAG = "protection1";

    private static final String PROT_PRIMARY = "protPrimary";
    private static final String PROT_BACKUP = "protBackup";


    private static final Mod MOD_PROT_PRIMARY = new Mod(PROT_PRIMARY);
    private static final Set<Mod> PROTECTED_MOD_PRIMARY_SET =
            ImmutableSet.of(MOD_PROT_PRIMARY);

    private static final Mod MOD_PROT_BACKUP = new Mod(PROT_BACKUP);
    private static final Set<Mod> PROTECTED_MOD_BACKUP_SET =
            ImmutableSet.of(MOD_PROT_BACKUP);


    /**
     * Designates the different modes of operation.
     */
    public enum ProtectedMode {
        IDLE,
        SELECTED_INTENT
    }

    private final long trafficPeriod;
    private final ServicesBundle services;
    private final TopologyViewMessageHandler msgHandler;

    private final Timer timer = new Timer("topo-protected-intents");

    private TimerTask trafficTask = null;
    private ProtectedMode mode = ProtectedMode.IDLE;
    private Intent selectedIntent = null;


    /**
     * Constructs a protected intent monitor.
     *
     * @param trafficPeriod traffic task period in ms
     * @param services      bundle of services
     * @param msgHandler    our message handler
     */
    public ProtectedIntentMonitor(long trafficPeriod, ServicesBundle services,
                                  TopologyViewMessageHandler msgHandler) {
        this.trafficPeriod = trafficPeriod;
        this.services = services;
        this.msgHandler = msgHandler;
    }

    // =======================================================================
    // === API ===

    // TODO: move this out to the "h2h/multi-intent app"

    /**
     * Monitor for protected intent data to be sent back to the web client,
     * for the given intent.
     *
     * @param intent the intent to monitor
     */
    public synchronized void monitor(Intent intent) {
        log.debug("monitor intent: {}", intent.id());
        selectedIntent = intent;
        mode = SELECTED_INTENT;
        scheduleTask();
        sendSelectedIntents();
    }

    /**
     * Stop all traffic monitoring.
     */
    public synchronized void stopMonitoring() {
        log.debug("STOP monitoring");
        if (mode != IDLE) {
            sendClearAll();
        }
    }


    // =======================================================================
    // === Helper methods ===
    private void sendClearAll() {
        clearAll();
        sendClearHighlights();
    }

    private void clearAll() {
        this.mode = IDLE;
        clearSelection();
        cancelTask();
    }

    private void clearSelection() {
        selectedIntent = null;
    }

    //TODO duplicate and can be brought in abstract upper class.
    private synchronized void scheduleTask() {
        if (trafficTask == null) {
            log.debug("Starting up background protected intent task...");
            trafficTask = new TrafficUpdateTask();
            timer.schedule(trafficTask, trafficPeriod, trafficPeriod);
        } else {
            log.debug("(protected intent task already running)");
        }
    }

    private synchronized void cancelTask() {
        if (trafficTask != null) {
            trafficTask.cancel();
            trafficTask = null;
        }
    }

    private void sendSelectedIntents() {
        log.debug("sendSelectedIntents: {}", selectedIntent);
        msgHandler.sendHighlights(protectedIntentHighlights());
    }

    private void sendClearHighlights() {
        log.debug("sendClearHighlights");
        msgHandler.sendHighlights(new Highlights());
    }

    // =======================================================================
    // === Generate messages in JSON object node format
    private Highlights protectedIntentHighlights() {
        Highlights highlights = new Highlights();
        TrafficLinkMap linkMap = new TrafficLinkMap();
        IntentService intentService = services.intent();
        if (selectedIntent != null) {
            List<Intent> installables = intentService.getInstallableIntents(selectedIntent.key());

            if (installables != null) {
                ProtectionEndpointIntent ep1 = installables.stream()
                        .filter(ProtectionEndpointIntent.class::isInstance)
                        .map(ProtectionEndpointIntent.class::cast)
                        .findFirst().orElse(null);
                ProtectionEndpointIntent ep2 = installables.stream()
                        .filter(ii -> !ii.equals(ep1))
                        .filter(ProtectionEndpointIntent.class::isInstance)
                        .map(ProtectionEndpointIntent.class::cast)
                        .findFirst().orElse(null);
                if (ep1 == null || ep2 == null) {
                    log.warn("Selected Intent {} didn't have 2 protection endpoints",
                             selectedIntent.key());
                    stopMonitoring();
                    return highlights;
                }
                Set<Link> primary = new LinkedHashSet<>();
                Set<Link> backup = new LinkedHashSet<>();

                Map<Boolean, List<FlowRuleIntent>> transits = installables.stream()
                        .filter(FlowRuleIntent.class::isInstance)
                        .map(FlowRuleIntent.class::cast)
                        // only consider fwd links so that ants march in one direction
                        // TODO: didn't help need further investigation.
                        //.filter(i -> !i.resources().contains(marker("rev")))
                        .collect(Collectors.groupingBy(this::isPrimary));

                // walk primary
                ConnectPoint primHead = ep1.description().paths().get(0).output().connectPoint();
                ConnectPoint primTail = ep2.description().paths().get(0).output().connectPoint();
                List<FlowRuleIntent> primTransit = transits.getOrDefault(true, ImmutableList.of());
                populateLinks(primary, primHead, primTail, primTransit);

                // walk backup
                ConnectPoint backHead = ep1.description().paths().get(1).output().connectPoint();
                ConnectPoint backTail = ep2.description().paths().get(1).output().connectPoint();
                List<FlowRuleIntent> backTransit = transits.getOrDefault(false, ImmutableList.of());
                populateLinks(backup, backHead, backTail, backTransit);

                // Add packet to optical links
                if (!usingBackup(primary)) {
                    primary.addAll(protectedIntentMultiLayer(primHead, primTail));
                }
                backup.addAll(protectedIntentMultiLayer(backHead, backTail));

                boolean isOptical = selectedIntent instanceof OpticalConnectivityIntent;
                //last parameter (traffic) signals if the link is highlighted with ants or solid line
                //Flavor is swapped so green is primary path.
                if (usingBackup(primary)) {
                    //the backup becomes in use so we have a dotted line
                    processLinks(linkMap, backup, Flavor.PRIMARY_HIGHLIGHT,
                                 isOptical, true, PROTECTED_MOD_BACKUP_SET);
                } else {
                    processLinks(linkMap, primary, Flavor.PRIMARY_HIGHLIGHT,
                                 isOptical, true, PROTECTED_MOD_PRIMARY_SET);
                    processLinks(linkMap, backup, Flavor.SECONDARY_HIGHLIGHT,
                                 isOptical, false, PROTECTED_MOD_BACKUP_SET);
                }

                updateHighlights(highlights, primary);
                updateHighlights(highlights, backup);
                colorLinks(highlights, linkMap);
                highlights.subdueAllElse(Highlights.Amount.MINIMALLY);
            } else {
                log.debug("Selected Intent has no installable intents");
            }
        } else {
            log.debug("Selected Intent is null");
        }
        return highlights;
    }

    /**
     * Returns the packet to optical mapping given a head and tail of a protection path.
     *
     * @param head head of path
     * @param tail tail of path
     */
    private Set<Link> protectedIntentMultiLayer(ConnectPoint head, ConnectPoint tail) {
        List<Link> links = new LinkedList<>();
        LinkService linkService = services.link();
        IntentService intentService = services.intent();

        // Ingress cross connect link
        links.addAll(
                linkService.getEgressLinks(head).stream()
                        .filter(l -> l.type() == Link.Type.OPTICAL)
                        .collect(Collectors.toList())
        );

        // Egress cross connect link
        links.addAll(
                linkService.getIngressLinks(tail).stream()
                        .filter(l -> l.type() == Link.Type.OPTICAL)
                        .collect(Collectors.toList())
        );

        // The protected intent does not rely on a multi-layer mapping
        if (links.size() != 2) {
            return Collections.emptySet();
        }

        // Expected head and tail of optical circuit (not connectivity!) intent
        ConnectPoint ocHead = links.get(0).dst();
        ConnectPoint ocTail = links.get(1).src();

        // Optical connectivity
        // FIXME: assumes that transponder (OTN device) is a one-to-one mapping
        // We need to track the multi-layer aspects better
        intentService.getIntents().forEach(intent -> {
            if (intent instanceof OpticalConnectivityIntent) {
                OpticalConnectivityIntent ocIntent = (OpticalConnectivityIntent) intent;
                if (ocHead.deviceId().equals(ocIntent.getSrc().deviceId()) &&
                        ocTail.deviceId().equals(ocIntent.getDst().deviceId())) {
                    intentService.getInstallableIntents(ocIntent.key()).forEach(i -> {
                        if (i instanceof FlowRuleIntent) {
                            FlowRuleIntent fr = (FlowRuleIntent) i;
                            links.addAll(linkResources(fr));
                        }
                    });
                }
            }
        });

        return new LinkedHashSet<>(links);
    }

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    /**
     * Populate Links along the primary/backup path.
     *
     * @param links   link collection to populate [output]
     * @param head    head-end of primary/backup path
     * @param tail    tail-end of primary/backup path
     * @param transit Intents if any
     */
    private void populateLinks(Set<Link> links,
                               ConnectPoint head,
                               ConnectPoint tail,
                               List<FlowRuleIntent> transit) {
        // find first hop link
        Link first = transit.stream()
                // search for Link head -> transit Intent head
                // as first candidate of 1st hop Link
                .flatMap(fri -> fri.flowRules().stream())
                .map(fr ->
                    // find first input port from FlowRule
                    Optional.ofNullable(fr.selector().getCriterion(Criterion.Type.IN_PORT))
                        .filter(PortCriterion.class::isInstance)
                        .map(PortCriterion.class::cast)
                        .map(PortCriterion::port)
                        .map(pn -> new ConnectPoint(fr.deviceId(), pn))
                        .orElse(null)
                ).filter(Objects::nonNull)
                .map(dst -> services.link().getLink(head, dst))
                .filter(Objects::nonNull)
                .findFirst()
                // if there isn't one probably 1 hop to the tail
                .orElse(services.link().getLink(head, tail));

        // add first link
        if (first != null) {
            links.add(first);
        }

        // add links in the middle if any
        transit.forEach(fri -> links.addAll(linkResources(fri)));

        // add last hop if any
        Lists.reverse(transit).stream()
                // search for Link transit Intent tail -> tail
                // as candidate of last hop Link
                .flatMap(fri -> ImmutableList.copyOf(fri.flowRules()).reverse().stream())
                .map(fr ->
                    // find first output port from FlowRule
                    fr.treatment().allInstructions().stream()
                            .filter(OutputInstruction.class::isInstance).findFirst()
                        .map(OutputInstruction.class::cast)
                        .map(OutputInstruction::port)
                        .map(pn -> new ConnectPoint(fr.deviceId(), pn))
                        .orElse(null)
                ).filter(Objects::nonNull)
                .map(src -> services.link().getLink(src, tail))
                .filter(Objects::nonNull)
                .findFirst()
                .ifPresent(links::add);
    }

    /**
     * Returns true if specified intent is marked with primary marker resource.
     *
     * @param intent to test
     * @return true if it is an Intent taking part of primary transit path
     */
    private boolean isPrimary(Intent intent) {
        return intent.resources()
                .contains(marker(PRIMARY_PATH_TAG));
    }

    // returns true if the backup path is the one where the traffic is currently flowing
    private boolean usingBackup(Set<Link> primary) {
        Set<Link> activeLinks = Sets.newHashSet(services.link().getActiveLinks());
        return primary.isEmpty() || !activeLinks.containsAll(primary);
    }

    private void updateHighlights(Highlights highlights, Iterable<Link> links) {
        for (Link link : links) {
            ensureNodePresent(highlights, link.src().elementId());
            ensureNodePresent(highlights, link.dst().elementId());
        }
    }

    //TODO duplicate and can be brought in abstract upper class.
    private void ensureNodePresent(Highlights highlights, ElementId eid) {
        String id = eid.toString();
        NodeHighlight nh = highlights.getNode(id);
        if (nh == null) {
            if (eid instanceof DeviceId) {
                nh = new DeviceHighlight(id);
                highlights.add((DeviceHighlight) nh);
            } else if (eid instanceof HostId) {
                nh = new HostHighlight(id);
                highlights.add((HostHighlight) nh);
            }
        }
    }

    private void processLinks(TrafficLinkMap linkMap, Iterable<Link> links,
                              Flavor flavor, boolean isOptical,
                              boolean showTraffic, Set<Mod> mods) {
        if (links != null) {
            for (Link link : links) {
                TrafficLink tlink = linkMap.add(link);
                tlink.tagFlavor(flavor);
                tlink.optical(isOptical);
                if (showTraffic) {
                    tlink.antMarch(true);
                }
                tlink.tagMods(mods);
            }
        }
    }

    //TODO duplicate and can be brought in abstract upper class.
    private void colorLinks(Highlights highlights, TrafficLinkMap linkMap) {
        for (TrafficLink tlink : linkMap.biLinks()) {
            highlights.add(tlink.highlight(StatsType.TAGGED));
        }
    }

    //TODO duplicate and can be brought in abstract upper class.
    // Extracts links from the specified flow rule intent resources
    private Collection<Link> linkResources(Intent installable) {
        ImmutableList.Builder<Link> builder = ImmutableList.builder();
        installable.resources().stream().filter(r -> r instanceof Link)
                .forEach(r -> builder.add((Link) r));
        return builder.build();
    }

    // =======================================================================
    // === Background Task

    // Provides periodic update of traffic information to the client
    private class TrafficUpdateTask extends TimerTask {
        @Override
        public void run() {
            try {
                switch (mode) {
                    case SELECTED_INTENT:
                        sendSelectedIntents();
                        break;

                    default:
                        // RELATED_INTENTS and IDLE modes should never invoke
                        // the background task, but if they do, they have
                        // nothing to do
                        break;
                }

            } catch (Exception e) {
                log.warn("Unable to process protected intent task due to {}", e.getMessage());
                log.warn("Boom!", e);
            }
        }
    }
}
