/*
 * 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.Sets;
import org.onosproject.net.DeviceId;
import org.onosproject.net.ElementId;
import org.onosproject.net.HostId;
import org.onosproject.net.Link;
import org.onosproject.net.MarkerResource;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.behaviour.protection.TransportEndpointDescription;
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.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;

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());
            Set<Link> primary = new HashSet<>();
            Set<Link> backup = new HashSet<>();
            if (installables != null) {
                //There should be exactly two FlowRuleIntent and four
                //ProtectionEndpointIntent for each ProtectedTransportIntent.
                for (Intent installable : installables) {
                    if (installable instanceof FlowRuleIntent) {
                        handleFlowRuleIntent(primary, backup, (FlowRuleIntent) installable);
                    } else if (installable instanceof ProtectionEndpointIntent) {
                        handleProtectionEndpointIntent(primary, backup,
                                                       (ProtectionEndpointIntent) installable);
                    } else {
                        log.warn("Intent {} is not an expected installable type {} " +
                                         "related to ProtectedTransportIntent",
                                 installable.id(), installable.getClass().getSimpleName());
                        stopMonitoring();
                    }
                }
                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;
    }

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

    private void handleProtectionEndpointIntent(Set<Link> primary, Set<Link> backup,
                                                ProtectionEndpointIntent peIntent) {
        TransportEndpointDescription primaryDesc = peIntent
                .description().paths().get(0);
        TransportEndpointDescription secondaryDesc = peIntent
                .description().paths().get(1);
        primary.addAll(servicesBundle.linkService()
                               .getLinks(primaryDesc.output()
                                                 .connectPoint()));
        backup.addAll(servicesBundle.linkService()
                              .getLinks(secondaryDesc.output()
                                                .connectPoint()));
    }

    private void handleFlowRuleIntent(Set<Link> primary, Set<Link> backup,
                                      FlowRuleIntent frIntent) {
        boolean protection1 = frIntent.resources().stream()
                .filter(r -> r instanceof MarkerResource)
                .map(NetworkResource::toString)
                .anyMatch(rstring -> rstring.equals(PRIMARY_PATH_TAG));
        if (protection1) {
            primary.addAll(linkResources(frIntent));
        } else {
            backup.addAll(linkResources(frIntent));
        }
    }

    // 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);
            }
        }
    }
}
