/*
 *  Copyright 2016-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.ui.impl.topo.util;

import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.Link;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.intent.FlowObjectiveIntent;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.HostToHostIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.LinkCollectionIntent;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.OpticalConnectivityIntent;
import org.onosproject.net.intent.PathIntent;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.net.link.LinkService;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import static org.onosproject.net.intent.IntentState.INSTALLED;

/**
 * Auxiliary facility to query the intent service based on the specified
 * set of end-station hosts, edge points or infrastructure devices.
 */
public class TopoIntentFilter {

    private final IntentService intentService;
    private final LinkService linkService;

    /**
     * Creates an intent filter.
     *
     * @param services service references bundle
     */
    public TopoIntentFilter(ServicesBundle services) {
        this.intentService = services.intent();
        this.linkService = services.link();
    }

    /**
     * Finds all path (host-to-host or point-to-point) intents that pertain
     * to the given hosts and devices.
     *
     * @param hosts   set of hosts to query by
     * @param devices set of devices to query by
     * @param links   set of links to query by
     * @return set of intents that 'match' all hosts, devices and links given
     */
    public List<Intent> findPathIntents(Set<Host> hosts,
                                        Set<Device> devices,
                                        Set<Link> links) {
        // start with all intents
        Iterable<Intent> sourceIntents = intentService.getIntents();

        // Derive from this the set of edge connect points.
        Set<ConnectPoint> edgePoints = getEdgePoints(hosts);

        // Iterate over all intents and produce a set that contains only those
        // intents that target all selected hosts or derived edge connect points.
        return getIntents(hosts, devices, links, edgePoints, sourceIntents);
    }


    // Produces a set of edge points from the specified set of hosts.
    private Set<ConnectPoint> getEdgePoints(Set<Host> hosts) {
        Set<ConnectPoint> edgePoints = new HashSet<>();
        for (Host host : hosts) {
            edgePoints.add(host.location());
        }
        return edgePoints;
    }

    // Produces a list of intents that target all selected hosts, devices, links or connect points.
    private List<Intent> getIntents(Set<Host> hosts, Set<Device> devices, Set<Link> links,
                                    Set<ConnectPoint> edgePoints,
                                    Iterable<Intent> sourceIntents) {
        List<Intent> intents = new ArrayList<>();
        if (hosts.isEmpty() && devices.isEmpty() && links.isEmpty()) {
            return intents;
        }

        Set<OpticalConnectivityIntent> opticalIntents = new HashSet<>();

        // Search through all intents and see if they are relevant to our search.
        for (Intent intent : sourceIntents) {
            if (intentService.getIntentState(intent.key()) == INSTALLED) {
                boolean isRelevant = false;
                if (intent instanceof HostToHostIntent) {
                    isRelevant = isIntentRelevantToHosts((HostToHostIntent) intent, hosts) &&
                            isIntentRelevantToDevices(intent, devices) && isIntentRelevantToLinks(intent, links);
                } else if (intent instanceof PointToPointIntent) {
                    isRelevant = isIntentRelevant((PointToPointIntent) intent, edgePoints) &&
                            isIntentRelevantToDevices(intent, devices) && isIntentRelevantToLinks(intent, links);
                } else if (intent instanceof MultiPointToSinglePointIntent) {
                    isRelevant = isIntentRelevant((MultiPointToSinglePointIntent) intent, edgePoints) &&
                            isIntentRelevantToDevices(intent, devices) && isIntentRelevantToLinks(intent, links);
                } else if (intent instanceof OpticalConnectivityIntent) {
                    opticalIntents.add((OpticalConnectivityIntent) intent);
                }
                // TODO: add other intents, e.g. SinglePointToMultiPointIntent

                if (isRelevant) {
                    intents.add(intent);
                }
            }
        }

        // As a second pass, try to link up any optical intents with the
        // packet-level ones.
        for (OpticalConnectivityIntent intent : opticalIntents) {
            if (isIntentRelevant(intent, intents) &&
                    isIntentRelevantToDevices(intent, devices)) {
                intents.add(intent);
            }
        }
        return intents;
    }

    // Indicates whether the specified intent involves all of the given hosts.
    private boolean isIntentRelevantToHosts(HostToHostIntent intent, Iterable<Host> hosts) {
        for (Host host : hosts) {
            HostId id = host.id();
            // Bail if intent does not involve this host.
            if (!id.equals(intent.one()) && !id.equals(intent.two())) {
                return false;
            }
        }
        return true;
    }

    // Indicates whether the specified intent involves all of the given devices.
    private boolean isIntentRelevantToDevices(Intent intent, Iterable<Device> devices) {
        List<Intent> installables = intentService.getInstallableIntents(intent.key());
        for (Device device : devices) {
            if (!isIntentRelevantToDevice(installables, device)) {
                return false;
            }
        }
        return true;
    }

    // Indicates whether the specified intent involves all of the given links.
    private boolean isIntentRelevantToLinks(Intent intent, Iterable<Link> links) {
        List<Intent> installables = intentService.getInstallableIntents(intent.key());
        for (Link link : links) {
            if (!isIntentRelevantToLink(installables, link)) {
                return false;
            }
        }
        return true;
    }

    // Indicates whether the specified intent involves the given device.
    private boolean isIntentRelevantToDevice(List<Intent> installables, Device device) {
        if (installables != null) {
            for (Intent installable : installables) {
                if (installable instanceof PathIntent) {
                    PathIntent pathIntent = (PathIntent) installable;
                    if (pathContainsDevice(pathIntent.path().links(), device.id())) {
                        return true;
                    }
                } else if (installable instanceof FlowRuleIntent) {
                    FlowRuleIntent flowRuleIntent = (FlowRuleIntent) installable;
                    if (rulesContainDevice(flowRuleIntent.flowRules(), device.id())) {
                        return true;
                    }
                } else if (installable instanceof FlowObjectiveIntent) {
                    FlowObjectiveIntent objectiveIntent = (FlowObjectiveIntent) installable;
                    return objectiveIntent.devices().contains(device.id());

                } else if (installable instanceof LinkCollectionIntent) {
                    LinkCollectionIntent linksIntent = (LinkCollectionIntent) installable;
                    if (pathContainsDevice(linksIntent.links(), device.id())) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    // Indicates whether the specified intent involves the given link.
    private boolean isIntentRelevantToLink(List<Intent> installables, Link link) {
        Link reverseLink = linkService.getLink(link.dst(), link.src());

        if (installables != null) {
            for (Intent installable : installables) {
                if (installable instanceof PathIntent) {
                    PathIntent pathIntent = (PathIntent) installable;
                    return pathIntent.path().links().contains(link) ||
                            pathIntent.path().links().contains(reverseLink);

                } else if (installable instanceof FlowRuleIntent) {
                    FlowRuleIntent flowRuleIntent = (FlowRuleIntent) installable;
                    return flowRuleIntent.resources().contains(link) ||
                            flowRuleIntent.resources().contains(reverseLink);

                } else if (installable instanceof FlowObjectiveIntent) {
                    FlowObjectiveIntent objectiveIntent = (FlowObjectiveIntent) installable;
                    return objectiveIntent.resources().contains(link) ||
                            objectiveIntent.resources().contains(reverseLink);

                } else if (installable instanceof LinkCollectionIntent) {
                    LinkCollectionIntent linksIntent = (LinkCollectionIntent) installable;
                    return linksIntent.links().contains(link) ||
                            linksIntent.links().contains(reverseLink);

                }
            }
        }
        return false;
    }

    // Indicates whether the specified links involve the given device.
    private boolean pathContainsDevice(Iterable<Link> links, DeviceId id) {
        for (Link link : links) {
            if (link.src().elementId().equals(id) || link.dst().elementId().equals(id)) {
                return true;
            }
        }
        return false;
    }

    // Indicates whether the specified flow rules involves the given device.
    private boolean rulesContainDevice(Collection<FlowRule> flowRules, DeviceId id) {
        for (FlowRule rule : flowRules) {
            if (rule.deviceId().equals(id)) {
                return true;
            }
        }
        return false;
    }

    private boolean isIntentRelevant(PointToPointIntent intent,
                                     Iterable<ConnectPoint> edgePoints) {
        for (ConnectPoint point : edgePoints) {
            // Bail if intent does not involve this edge point.
            if (!point.equals(intent.filteredEgressPoint().connectPoint()) &&
                    !point.equals(intent.filteredIngressPoint().connectPoint())) {
                return false;
            }
        }
        return true;
    }

    // Indicates whether the specified intent involves all of the given edge points.
    private boolean isIntentRelevant(MultiPointToSinglePointIntent intent,
                                     Iterable<ConnectPoint> edgePoints) {
        for (ConnectPoint point : edgePoints) {
            // Bail if intent does not involve this edge point.
            if (!point.equals(intent.egressPoint()) &&
                    !intent.ingressPoints().contains(point)) {
                return false;
            }
        }
        return true;
    }

    // Indicates whether the specified intent involves all of the given edge points.
    private boolean isIntentRelevant(OpticalConnectivityIntent opticalIntent,
                                     Iterable<Intent> intents) {
        Link ccSrc = getFirstLink(opticalIntent.getSrc(), false);
        Link ccDst = getFirstLink(opticalIntent.getDst(), true);
        if (ccSrc == null || ccDst == null) {
            return false;
        }

        for (Intent intent : intents) {
            List<Intent> installables = intentService.getInstallableIntents(intent.key());
            for (Intent installable : installables) {
                if (installable instanceof PathIntent) {
                    List<Link> links = ((PathIntent) installable).path().links();
                    if (links.size() == 3) {
                        Link tunnel = links.get(1);
                        if (Objects.equals(tunnel.src(), ccSrc.src()) &&
                                Objects.equals(tunnel.dst(), ccDst.dst())) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    private Link getFirstLink(ConnectPoint point, boolean ingress) {
        for (Link link : linkService.getLinks(point)) {
            if (point.equals(ingress ? link.src() : link.dst())) {
                return link;
            }
        }
        return null;
    }
}
