/*
 * 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.OpticalConnectivityIntent;
import org.onosproject.net.intent.ProtectionEndpointIntent;
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.LinkedHashSet;
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 servicesBundle;
    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 servicesBundle bundle of services
     * @param msgHandler     our message handler
     */
    public ProtectedIntentMonitor(long trafficPeriod, ServicesBundle servicesBundle,
                                  TopologyViewMessageHandler msgHandler) {
        this.trafficPeriod = trafficPeriod;
        this.servicesBundle = servicesBundle;
        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();
        if (selectedIntent != null) {
            List<Intent> installables = servicesBundle.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);

                boolean isOptical = selectedIntent instanceof OpticalConnectivityIntent;
                //last parameter (traffic) signals if the link is highlited 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 installables intents");
            }
        } else {
            log.debug("Selected Intent is null");
        }
        return highlights;
    }

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

    /**
     * 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 -> servicesBundle.linkService().getLink(head, dst))
                .filter(Objects::nonNull)
                .findFirst()
                // if there isn't one probably 1 hop to the tail
                .orElse(servicesBundle.linkService().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 -> servicesBundle.linkService().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(servicesBundle.linkService().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);
            }
        }
    }
}
