/*
 * 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.utils;

import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.Member;
import org.onosproject.core.Application;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.intf.Interface;
import org.onosproject.net.TenantId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Element;
import org.onosproject.net.ElementId;
import org.onosproject.net.Port;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.group.Group;
import org.onosproject.net.key.DeviceKey;
import org.onosproject.net.region.Region;
import org.onosproject.net.statistic.FlowEntryWithLoad;
import org.onosproject.net.topology.TopologyCluster;
import org.onosproject.ui.model.topo.UiTopoLayout;

import java.util.Comparator;

/**
 * Various comparators.
 */
public final class Comparators {

    // Ban construction
    private Comparators() {
    }

    public static final Comparator<ApplicationId> APP_ID_COMPARATOR =
            (id1, id2) -> id1.id() - id2.id();

    public static final Comparator<Application> APP_COMPARATOR =
            (app1, app2) -> app1.id().id() - app2.id().id();

    public static final Comparator<ElementId> ELEMENT_ID_COMPARATOR =
            (id1, id2) -> id1.toString().compareTo(id2.toString());

    public static final Comparator<Element> ELEMENT_COMPARATOR =
            (e1, e2) -> e1.id().toString().compareTo(e2.id().toString());

    public static final Comparator<FlowRule> FLOW_RULE_COMPARATOR =
            (f1, f2) -> {
                // Compare table IDs in ascending order
                int tableCompare = f1.table().compareTo(f2.table());
                if (tableCompare != 0) {
                    return tableCompare;
                }
                // Compare priorities in descending order
                int priorityCompare = f2.priority() - f1.priority();
                return (priorityCompare == 0)
                        ? Long.compare(f1.id().value(), f2.id().value())
                        : priorityCompare;
            };

    public static final Comparator<FlowEntryWithLoad> FLOWENTRY_WITHLOAD_COMPARATOR =
            (fe1, fe2) -> {
                long delta = fe1.load().rate() - fe2.load().rate();
                return delta == 0 ? 0 : (delta > 0 ? -1 : +1);
            };

    public static final Comparator<Group> GROUP_COMPARATOR =
            (g1, g2) -> Long.valueOf(g1.id().id()).compareTo((long) g2.id().id());

    public static final Comparator<Port> PORT_COMPARATOR =
            (p1, p2) -> {
                long delta = p1.number().toLong() - p2.number().toLong();
                return delta == 0 ? 0 : (delta < 0 ? -1 : +1);
            };

    public static final Comparator<TopologyCluster> CLUSTER_COMPARATOR =
            (c1, c2) -> c1.id().index() - c2.id().index();

    public static final Comparator<ControllerNode> NODE_COMPARATOR =
            (ci1, ci2) -> ci1.id().toString().compareTo(ci2.id().toString());

    public static final Comparator<Member> MEMBERSHIP_COMPARATOR =
            (ci1, ci2) -> ci1.nodeId().toString().compareTo(ci2.nodeId().toString());

    public static final Comparator<ConnectPoint> CONNECT_POINT_COMPARATOR =
            (o1, o2) -> {
                int compareId = ELEMENT_ID_COMPARATOR.compare(o1.elementId(), o2.elementId());
                return (compareId != 0) ?
                        compareId :
                        Long.signum(o1.port().toLong() - o2.port().toLong());
            };

    public static final Comparator<Interface> INTERFACES_COMPARATOR =
            (intf1, intf2) ->
                    CONNECT_POINT_COMPARATOR.compare(intf1.connectPoint(), intf2.connectPoint());

    public static final Comparator<DeviceKey> DEVICE_KEY_COMPARATOR =
            (dk1, dk2) -> dk1.deviceKeyId().id().compareTo(dk2.deviceKeyId().id());

    public static final Comparator<Region> REGION_COMPARATOR =
            (r1, r2) -> r1.id().toString().compareTo(r2.id().toString());

    public static final Comparator<UiTopoLayout> LAYOUT_COMPARATOR =
            (l1, l2) -> l1.id().toString().compareTo(l2.id().toString());

    public static final Comparator<TenantId> TENANT_ID_COMPARATOR =
            (t1, t2) -> t1.id().compareTo(t2.id());

}
