/*
 * Copyright 2015-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.topo;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.Element;
import org.onosproject.net.Host;
import org.onosproject.net.Link;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.host.HostService;
import org.onosproject.net.link.LinkService;
import org.onosproject.ui.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onosproject.net.ConnectPoint.deviceConnectPoint;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.HostId.hostId;

/**
 * Encapsulates a selection of devices, hosts and links from the topology view.
 */
public class NodeSelection {

    private static final Logger log =
            LoggerFactory.getLogger(NodeSelection.class);

    private static final String IDS = "ids";
    private static final String HOVER = "hover";
    private static final String LINK_ID_DELIM = "-";

    private final DeviceService deviceService;
    private final HostService hostService;
    private final LinkService linkService;

    private final Set<String> ids;
    private final String hover;

    private final Set<Device> devices = new HashSet<>();
    private final Set<Host> hosts = new HashSet<>();
    private final Set<Link> links = new HashSet<>();
    private Element hovered;

    /**
     * Creates a node selection entity, from the given payload, using the
     * supplied link, device and host services. Note that if a link, device
     * or host was hovered over by the mouse, it is available
     * via {@link #hovered()}.
     *
     * @param payload message payload
     * @param deviceService device service
     * @param hostService host service
     * @param linkService link service
     */
    public NodeSelection(ObjectNode payload,
                         DeviceService deviceService,
                         HostService hostService,
                         LinkService linkService) {
        this.deviceService = deviceService;
        this.hostService = hostService;
        this.linkService = linkService;

        ids = extractIds(payload);
        hover = extractHover(payload);

        // start by extracting the hovered element if any
        if (isNullOrEmpty(hover)) {
            hovered = null;
        } else {
            setHoveredElement();
        }

        // now go find the links, devices and hosts that are in the selection list
        Set<String> unmatched = findLinks(ids);
        unmatched = findDevices(unmatched);
        unmatched = findHosts(unmatched);
        if (!unmatched.isEmpty()) {
            log.debug("Skipping unmatched IDs {}", unmatched);
        }

    }

    /**
     * Returns a view of the selected devices (hover not included).
     *
     * @return selected devices
     */
    public Set<Device> devices() {
        return Collections.unmodifiableSet(devices);
    }

    /**
     * Returns a view of the selected links (hover not included).
     *
     * @return selected links
     */
    public Set<Link> links() {
        return Collections.unmodifiableSet(links);
    }

    /**
     * Returns a view of the selected devices, including the hovered device
     * if there was one.
     *
     * @return selected (plus hovered) devices
     */
    public Set<Device> devicesWithHover() {
        Set<Device> withHover;
        if (hovered != null && hovered instanceof Device) {
            withHover = new HashSet<>(devices);
            withHover.add((Device) hovered);
        } else {
            withHover = devices;
        }
        return Collections.unmodifiableSet(withHover);
    }

    /**
     * Returns a view of the selected hosts (hover not included).
     *
     * @return selected hosts
     */
    public Set<Host> hosts() {
        return Collections.unmodifiableSet(hosts);
    }

    /**
     * Returns a view of the selected hosts, including the hovered host
     * if thee was one.
     *
     * @return selected (plus hovered) hosts
     */
    public Set<Host> hostsWithHover() {
        Set<Host> withHover;
        if (hovered != null && hovered instanceof Host) {
            withHover = new HashSet<>(hosts);
            withHover.add((Host) hovered);
        } else {
            withHover = hosts;
        }
        return Collections.unmodifiableSet(withHover);
    }

    /**
     * Returns a view of the selected links, including the hovered link
     * if thee was one.
     *
     * @return selected (plus hovered) links
     */
    public Set<Link> linksWithHover() {
        Set<Link> withHover;
        if (hovered != null && hovered instanceof Link) {
            withHover = new HashSet<>(links);
            withHover.add((Link) hovered);
        } else {
            withHover = links;
        }
        return Collections.unmodifiableSet(withHover);
    }

    /**
     * Returns the element (link, host or device) over which the mouse was hovering,
     * or null.
     *
     * @return element hovered over
     */
    public Element hovered() {
        return hovered;
    }

    /**
     * Returns true if nothing is selected.
     *
     * @return true if nothing selected
     */
    public boolean none() {
        return devices().isEmpty() && hosts().isEmpty() && links().isEmpty();
    }

    @Override
    public String toString() {
        return "NodeSelection{" +
                "ids=" + ids +
                ", hover='" + hover + '\'' +
                ", #devices=" + devices.size() +
                ", #hosts=" + hosts.size() +
                ", #links=" + links.size() +
                '}';
    }

    // == helper methods

    private Set<String> extractIds(ObjectNode payload) {
        ArrayNode array = (ArrayNode) payload.path(IDS);
        if (array == null || array.size() == 0) {
            return Collections.emptySet();
        }

        Set<String> ids = new HashSet<>();
        for (JsonNode node : array) {
            ids.add(node.asText());
        }
        return ids;
    }

    private String extractHover(ObjectNode payload) {
        return JsonUtils.string(payload, HOVER);
    }

    private void setHoveredElement() {
        Set<String> unmatched;
        unmatched = new HashSet<>();
        unmatched.add(hover);
        unmatched = findDevices(unmatched);
        if (devices.size() == 1) {
            hovered = devices.iterator().next();
            devices.clear();
        } else {
            unmatched = findHosts(unmatched);
            if (hosts.size() == 1) {
                hovered = hosts.iterator().next();
                hosts.clear();
            } else {
                hovered = null;
                log.debug("Skipping unmatched HOVER {}", unmatched);
            }
        }
    }

    private Set<String> findDevices(Set<String> ids) {
        Set<String> unmatched = new HashSet<>();
        Device device;

        for (String id : ids) {
            try {
                device = deviceService.getDevice(deviceId(id));
                if (device != null) {
                    devices.add(device);
                } else {
                    unmatched.add(id);
                }
            } catch (Exception e) {
                unmatched.add(id);
            }
        }
        return unmatched;
    }

    private Set<String> findHosts(Set<String> ids) {
        Set<String> unmatched = new HashSet<>();
        Host host;

        for (String id : ids) {
            try {
                host = hostService.getHost(hostId(id));
                if (host != null) {
                    hosts.add(host);
                } else {
                    unmatched.add(id);
                }
            } catch (Exception e) {
                unmatched.add(id);
            }
        }
        return unmatched;
    }

    private Set<String> findLinks(Set<String> ids) {
        Set<String> unmatched = new HashSet<>();
        ConnectPoint cpSrc, cpDst;
        Link link;

        for (String id : ids) {
            try {
                String[] connectPoints = id.split(LINK_ID_DELIM);
                if (connectPoints.length != 2) {
                    unmatched.add(id);
                    continue;
                }

                cpSrc = deviceConnectPoint(connectPoints[0]);
                cpDst = deviceConnectPoint(connectPoints[1]);
                link = linkService.getLink(cpSrc, cpDst);

                if (link != null) {
                    links.add(link);
                } else {
                    unmatched.add(id);
                }

            } catch (Exception e) {
                unmatched.add(id);
            }
        }
        return unmatched;
    }
}
