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

import com.google.common.collect.ImmutableSet;
import org.onosproject.net.DeviceId;
import org.onosproject.net.HostId;
import org.onosproject.net.region.Region;
import org.onosproject.net.region.RegionId;

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

import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.region.RegionId.regionId;

/**
 * Represents a region.
 */
public class UiRegion extends UiNode {

    private static final String NULL_NAME = "(root)";
    private static final String NO_NAME = "???";

    /**
     * The identifier for the null-region. That is, a container for devices,
     * hosts, and links for those that belong to no region.
     */
    public static final RegionId NULL_ID = regionId(NULL_NAME);

    private static final String[] DEFAULT_LAYER_TAGS = {
            UiNode.LAYER_OPTICAL,
            UiNode.LAYER_PACKET,
            UiNode.LAYER_DEFAULT
    };

    // loose bindings to things in this region
    private final Set<DeviceId> deviceIds = new HashSet<>();
    private final Set<HostId> hostIds = new HashSet<>();

    private final List<String> layerOrder = new ArrayList<>();

    private final UiTopology topology;

    private final RegionId regionId;

    // keep track of hierarchy (inferred from UiTopoLayoutService)
    private RegionId parent;
    private final Set<RegionId> kids = new HashSet<>();

    /**
     * Constructs a UI region, with a reference to the specified backing region.
     *
     * @param topology parent topology
     * @param region   backing region
     */
    public UiRegion(UiTopology topology, Region region) {
        // Implementation Note: if region is null, this UiRegion is being used
        //  as a container for devices, hosts, links that belong to no region.
        this.topology = topology;
        this.regionId = region == null ? NULL_ID : region.id();

        setLayerOrder(DEFAULT_LAYER_TAGS);
    }

    @Override
    protected void destroy() {
        deviceIds.clear();
        hostIds.clear();
    }

    /**
     * Sets the layer order for this region.
     * Typically, the {@code UiNode.LAYER_*} constants will be used here.
     *
     * @param layers the layers
     */
    public void setLayerOrder(String... layers) {
        layerOrder.clear();
        Collections.addAll(layerOrder, layers);
    }

    /**
     * Returns the identity of the region.
     *
     * @return region ID
     */
    public RegionId id() {
        return regionId;
    }

    /**
     * Returns the identity of the parent region.
     *
     * @return parent region ID
     */
    public RegionId parent() {
        return parent;
    }

    /**
     * Returns true if this is the root (default) region.
     *
     * @return true if root region
     */
    public boolean isRoot() {
        return id().equals(parent);
    }

    /**
     * Returns the identities of the child regions.
     *
     * @return child region IDs
     */
    public Set<RegionId> children() {
        return ImmutableSet.copyOf(kids);
    }

    /**
     * Returns the UI region that is the parent of this region.
     *
     * @return the parent region
     */
    public UiRegion parentRegion() {
        return topology.findRegion(parent);
    }

    /**
     * Sets the parent ID for this region.
     *
     * @param parentId parent ID
     */
    public void setParent(RegionId parentId) {
        parent = parentId;
    }

    /**
     * Sets the children IDs for this region.
     *
     * @param children children IDs
     */
    public void setChildren(Set<RegionId> children) {
        kids.clear();
        kids.addAll(children);
    }

    @Override
    public String idAsString() {
        return id().toString();
    }

    @Override
    public String name() {
        Region region = backingRegion();
        return region == null ? NULL_NAME : region.name();
    }

    /**
     * Returns the region instance backing this UI region. If this instance
     * represents the "null-region", the value returned will be null.
     *
     * @return the backing region instance
     */
    public Region backingRegion() {
        return topology.services.region().getRegion(regionId);
    }

    /**
     * Make sure we have only these devices in the region.
     *
     * @param devices devices in the region
     */
    public void reconcileDevices(Set<DeviceId> devices) {
        deviceIds.clear();
        deviceIds.addAll(devices);
    }

    @Override
    public String toString() {
        return toStringHelper(this)
                .add("id", id())
                .add("name", name())
                .add("parent", parent)
                .add("kids", kids)
                .add("devices", deviceIds)
                .add("#hosts", hostIds.size())
                .toString();
    }

    /**
     * Returns the region's type.
     *
     * @return region type
     */
    public Region.Type type() {
        Region region = backingRegion();
        return region == null ? null : region.type();
    }


    /**
     * Returns the count of devices in this region.
     *
     * @return the device count
     */
    public int deviceCount() {
        return deviceIds.size();
    }

    /**
     * Returns the set of device identifiers for this region.
     *
     * @return device identifiers for this region
     */
    public Set<DeviceId> deviceIds() {
        return ImmutableSet.copyOf(deviceIds);
    }

    /**
     * Returns the devices in this region.
     *
     * @return the devices in this region
     */
    public Set<UiDevice> devices() {
        return topology.deviceSet(deviceIds);
    }


    /**
     * Make sure we have only these hosts in the region.
     *
     * @param hosts hosts in the region
     */
    public void reconcileHosts(Set<HostId> hosts) {
        hostIds.clear();
        hostIds.addAll(hosts);
    }

    /**
     * Returns the set of host identifiers for this region.
     *
     * @return host identifiers for this region
     */
    public Set<HostId> hostIds() {
        return ImmutableSet.copyOf(hostIds);
    }

    /**
     * Returns the hosts in this region.
     *
     * @return the hosts in this region
     */
    public Set<UiHost> hosts() {
        return topology.hostSet(hostIds);
    }

    /**
     * Returns the count of devices in this region.
     *
     * @return the device count
     */
    public int hostCount() {
        return hostIds.size();
    }

    /**
     * Returns the order in which layers should be rendered. Lower layers
     * come earlier in the list. For example, to indicate that nodes in the
     * optical layer should be rendered "below" nodes in the packet layer,
     * this method should return:
     * <pre>
     * [UiNode.LAYER_OPTICAL, UiNode.LAYER_PACKET, UiNode.LAYER_DEFAULT]
     * </pre>
     *
     * @return layer ordering
     */
    public List<String> layerOrder() {
        return Collections.unmodifiableList(layerOrder);
    }

    /**
     * Guarantees to return a string for the name of the specified region.
     * If region is null, we return the null region name, else we return
     * the name as configured on the region.
     *
     * @param region the region whose name we require
     * @return the region's name
     */
    public static String safeName(Region region) {
        if (region == null) {
            return NULL_NAME;
        }
        String name = region.name();
        return isNullOrEmpty(name) ? NO_NAME : name;
    }

    /**
     * Determins whether the specified event is relevant to the view
     * constrained to this region.
     *
     * @param event UI model event
     * @return true if relevant
     */
    public boolean isRelevant(UiModelEvent event) {
        switch (event.type()) {
            case CLUSTER_MEMBER_ADDED_OR_UPDATED:
            case CLUSTER_MEMBER_REMOVED:
                return true;

            case REGION_ADDED_OR_UPDATED:
            case REGION_REMOVED:
                return isRegionRelevant(((UiRegion) event.subject()).id());

            case DEVICE_ADDED_OR_UPDATED:
            case DEVICE_REMOVED:
                return isDeviceRelevant(((UiDevice) event.subject()).id());

            case LINK_ADDED_OR_UPDATED:
            case LINK_REMOVED:
                return isLinkRelevant((UiLink) event.subject());

            case HOST_ADDED_OR_UPDATED:
            case HOST_MOVED:
            case HOST_REMOVED:
                return isDeviceRelevant(((UiHost) event.subject()).locationDevice());

            default:
                return true;
        }
    }

    private boolean isDeviceRelevant(DeviceId deviceId) {
        return deviceIds.contains(deviceId);
    }

    private boolean isLinkRelevant(UiLink uiLink) {
        if (uiLink instanceof UiDeviceLink) {
            UiDeviceLink uiDeviceLink = (UiDeviceLink) uiLink;
            return isDeviceRelevant(uiDeviceLink.deviceA()) ||
                    isDeviceRelevant(uiDeviceLink.deviceB());

        } else if (uiLink instanceof UiRegionLink) {
            UiRegionLink uiRegionLink = (UiRegionLink) uiLink;
            return isRegionRelevant(uiRegionLink.regionA()) ||
                    isRegionRelevant(uiRegionLink.regionB());

        } else if (uiLink instanceof UiRegionDeviceLink) {
            UiRegionDeviceLink uiRegionDeviceLink = (UiRegionDeviceLink) uiLink;
            return isRegionRelevant(uiRegionDeviceLink.region()) ||
                    isDeviceRelevant(uiRegionDeviceLink.device());

        } else if (uiLink instanceof UiEdgeLink) {
            UiEdgeLink uiEdgeLink = (UiEdgeLink) uiLink;
            return isDeviceRelevant(uiEdgeLink.deviceId());
        }
        return false;
    }

    private boolean isRegionRelevant(RegionId regionId) {
        return kids.contains(regionId);
    }
}
