/*
 * Copyright 2017-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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.onosproject.app.DefaultApplicationDescriptionTest.APPS;
import static org.onosproject.app.DefaultApplicationDescriptionTest.CATEGORY;
import static org.onosproject.app.DefaultApplicationDescriptionTest.DESC;
import static org.onosproject.app.DefaultApplicationDescriptionTest.FEATURES;
import static org.onosproject.app.DefaultApplicationDescriptionTest.FURL;
import static org.onosproject.app.DefaultApplicationDescriptionTest.ICON;
import static org.onosproject.app.DefaultApplicationDescriptionTest.ORIGIN;
import static org.onosproject.app.DefaultApplicationDescriptionTest.PERMS;
import static org.onosproject.app.DefaultApplicationDescriptionTest.README;
import static org.onosproject.app.DefaultApplicationDescriptionTest.ROLE;
import static org.onosproject.app.DefaultApplicationDescriptionTest.TITLE;
import static org.onosproject.app.DefaultApplicationDescriptionTest.URL;
import static org.onosproject.app.DefaultApplicationDescriptionTest.VER;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.NetTestTools.APP_ID;
import static org.onosproject.net.NetTestTools.did;
import static org.onosproject.net.topology.ClusterId.clusterId;
import static org.onosproject.utils.Comparators.APP_COMPARATOR;
import static org.onosproject.utils.Comparators.APP_ID_COMPARATOR;
import static org.onosproject.utils.Comparators.CLUSTER_COMPARATOR;
import static org.onosproject.utils.Comparators.DEVICE_KEY_COMPARATOR;
import static org.onosproject.utils.Comparators.ELEMENT_COMPARATOR;
import static org.onosproject.utils.Comparators.ELEMENT_ID_COMPARATOR;
import static org.onosproject.utils.Comparators.FLOWENTRY_WITHLOAD_COMPARATOR;
import static org.onosproject.utils.Comparators.FLOW_RULE_COMPARATOR;
import static org.onosproject.utils.Comparators.GROUP_COMPARATOR;
import static org.onosproject.utils.Comparators.INTERFACES_COMPARATOR;
import static org.onosproject.utils.Comparators.LAYOUT_COMPARATOR;
import static org.onosproject.utils.Comparators.NODE_COMPARATOR;
import static org.onosproject.utils.Comparators.PORT_COMPARATOR;
import static org.onosproject.utils.Comparators.REGION_COMPARATOR;
import static org.onosproject.utils.Comparators.TENANT_ID_COMPARATOR;

import java.util.Optional;

import org.junit.Test;
import org.onlab.packet.ChassisId;
import org.onlab.packet.Ip4Address;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.DefaultControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.core.Application;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.DefaultApplication;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.core.GroupId;
import org.onosproject.net.intf.Interface;
import org.onosproject.net.TenantId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Element;
import org.onosproject.net.ElementId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowEntry;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.group.DefaultGroup;
import org.onosproject.net.group.DefaultGroupBucket;
import org.onosproject.net.group.DefaultGroupDescription;
import org.onosproject.net.group.Group;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.key.DeviceKey;
import org.onosproject.net.key.DeviceKeyId;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.region.DefaultRegion;
import org.onosproject.net.region.Region;
import org.onosproject.net.region.RegionId;
import org.onosproject.net.statistic.DefaultLoad;
import org.onosproject.net.statistic.FlowEntryWithLoad;
import org.onosproject.net.topology.DefaultTopologyCluster;
import org.onosproject.net.topology.DefaultTopologyVertex;
import org.onosproject.net.topology.TopologyCluster;
import org.onosproject.ui.model.topo.UiTopoLayout;
import org.onosproject.ui.model.topo.UiTopoLayoutId;

import com.google.common.collect.ImmutableList;


public class ComparatorsTest {
    private static final String MFR = "whitebox";
    private static final String HW1 = "2.2.x";
    private static final String SW1 = "4.0.0";
    private static final String SN = "43311-12345";
    private static final ChassisId CID = new ChassisId();
    private final ConnectPoint cp =
            new ConnectPoint(DeviceId.deviceId("of:00001"), PortNumber.portNumber(100));
    private final GroupBucket testBucket =
            DefaultGroupBucket.createAllGroupBucket(DefaultTrafficTreatment.emptyTreatment());
    private final GroupBuckets groupBuckets =
            new GroupBuckets(ImmutableList.of(testBucket));
    private final GroupDescription groupDesc1 =
            new DefaultGroupDescription(did("1"),
                    GroupDescription.Type.ALL,
                    groupBuckets);
    private final DefaultFlowEntry fEntry = new DefaultFlowEntry(fRule(10, 10),
            FlowEntry.FlowEntryState.ADDED, 5, 5, 5);
    Ip4Address ipAddress;

    @Test
    public void testAppIdComparator() {
        assertEquals(0, APP_ID_COMPARATOR.compare(appID(1, "a"), appID(1, "a")));
        assertTrue(APP_ID_COMPARATOR.compare(appID(2, "a"), appID(0, "a")) > 0);
        assertTrue(APP_ID_COMPARATOR.compare(appID(1, "b"), appID(3, "x")) < 0);
    }

    private ApplicationId appID(int id, String name) {
        return new DefaultApplicationId(id, name);
    }

    @Test
    public void testAppComparator() {
        assertEquals(0, APP_COMPARATOR.compare(app(1, "foo"), app(1, "foo")));
        assertEquals(0, (APP_COMPARATOR.compare(app(2, "foo"), app(2, "bar"))));
        assertNotEquals(0, APP_COMPARATOR.compare(app(1, "foo"), app(2, "foo")));
        assertNotEquals(0, APP_COMPARATOR.compare(app(1, "bar"), app(2, "foo")));
    }

    private Application app(int id, String name) {
        return DefaultApplication.builder()
                .withAppId(new DefaultApplicationId(id, name))
                .withVersion(VER)
                .withTitle(TITLE)
                .withDescription(DESC)
                .withOrigin(ORIGIN)
                .withCategory(CATEGORY)
                .withUrl(URL)
                .withReadme(README)
                .withIcon(ICON)
                .withRole(ROLE)
                .withPermissions(PERMS)
                .withFeaturesRepo(Optional.of(FURL))
                .withFeatures(FEATURES)
                .withRequiredApps(APPS)
                .build();
    }

    @Test
    public void testElementIdComparator() {
        ElementId elementid1 = new ElementId() {
        };
        ElementId elementid2 = elementid1;
        ElementId elementid3 = new ElementId() {
        };
        while (elementid1 == elementid3) {
            elementid3 = new ElementId() {
            };
        }
        assertTrue(0 == ELEMENT_ID_COMPARATOR.compare(elementid1, elementid2));
        assertFalse(0 == ELEMENT_ID_COMPARATOR.compare(elementid3, elementid1));
    }

    @Test
    public void testFlowRuleComparator() {
        assertEquals(0, FLOW_RULE_COMPARATOR.compare(fRule(100, 10), fRule(100, 10)));
        assertEquals(-8, FLOW_RULE_COMPARATOR.compare(fRule(100, 10), fRule(100, 2)));
        assertEquals(90, FLOW_RULE_COMPARATOR.compare(fRule(100, 10), fRule(10, 10)));
        assertEquals(20, FLOW_RULE_COMPARATOR.compare(fRule(40, 10), fRule(20, 2)));

    }

    private FlowRule fRule(int tableID, int priority) {
        return DefaultFlowRule.builder()
                .forDevice(did("id" + Integer.toString(10)))
                .withPriority(priority)
                .forTable(tableID)
                .fromApp(APP_ID)
                .makeTemporary(44)
                .build();
    }

    @Test
    public void testFlowEntryWithLoad() {
        //Rate = (current-previous)/interval
        assertEquals(0, FLOWENTRY_WITHLOAD_COMPARATOR.compare(flowEntryWithLoad(20, 10, 1),
                                                              flowEntryWithLoad(20, 10, 1)));
        assertEquals(0, FLOWENTRY_WITHLOAD_COMPARATOR.compare(flowEntryWithLoad(50, 30, 2),
                                                              flowEntryWithLoad(100, 50, 5)));
        assertEquals(-1, FLOWENTRY_WITHLOAD_COMPARATOR.compare(flowEntryWithLoad(200, 100, 4),
                                                               flowEntryWithLoad(300, 200, 10)));
    }

    private FlowEntryWithLoad flowEntryWithLoad(long current, long previous, long interval) {
        return new FlowEntryWithLoad(cp, fEntry, new DefaultLoad(current, previous, interval));
    }

    @Test
    public void testElementComparator() {
        assertEquals(0, ELEMENT_COMPARATOR.compare(element("of", "foo", "of:foo"), element("of", "foo", "of:foo")));
        assertEquals(0, ELEMENT_COMPARATOR.compare(element("of", "bar", "of:bar"), element("of", "foo", "of:bar")));
        assertNotEquals(0, ELEMENT_COMPARATOR.compare(element("of", "foo", "of:foo"), element("of", "foo", "of:bar")));
    }

    private Element element(String scheme, String provID, String devID) {
        return new DefaultDevice((new ProviderId(scheme, provID)), deviceId(devID), null, MFR, HW1, SW1, SN, CID);
    }

    @Test
    public void testGroupComparator() {
        assertEquals(0, GROUP_COMPARATOR.compare(group(10), group(10)));
        assertEquals(-1, GROUP_COMPARATOR.compare(group(25), group(100)));
        assertEquals(1, GROUP_COMPARATOR.compare(group(20), group(10)));
    }

    private Group group(int id) {
        return new DefaultGroup(new GroupId(id), groupDesc1);
    }

    @Test
    public void testPortComparator() {
        assertEquals(0, PORT_COMPARATOR.compare(portTest(100), portTest(100)));
        assertNotEquals(0, PORT_COMPARATOR.compare(portTest(100), portTest(200)));
    }

    private Port portTest(long portNumber) {
        return new DefaultPort(null, PortNumber.portNumber(portNumber), true, Port.Type.COPPER, 100);
    }

    @Test
    public void testTopologyClusterTest() {
        assertEquals(0, CLUSTER_COMPARATOR.compare(cluster(3, 2, 1, "of:1"), cluster(3, 2, 1, "of:1")));
        assertNotEquals(0, CLUSTER_COMPARATOR.compare(cluster(5, 2, 1, "of:1"), cluster(3, 2, 1, "of:1")));
    }

    private TopologyCluster cluster(int id, int dc, int lc, String root) {
        return new DefaultTopologyCluster(clusterId(id), dc, lc,
                new DefaultTopologyVertex(deviceId(root)));
    }

    @Test
    public void testControllerNode() {
        assertEquals(0, NODE_COMPARATOR.compare(node("testId"), node("testId")));
        assertTrue(NODE_COMPARATOR.compare(node("abc"), node("xyz")) < 0);
        assertTrue(NODE_COMPARATOR.compare(node("xyz"), node("abc")) > 0);
    }

    private ControllerNode node(String id) {
        return new DefaultControllerNode(NodeId.nodeId(id), ipAddress, 9876);
    }

    @Test
    public void testInterfaceComparator() {
        assertEquals(0, INTERFACES_COMPARATOR.compare(intface("of:0000000000000001", 100),
                                                      intface("of:0000000000000001", 100)));
        assertTrue(INTERFACES_COMPARATOR.compare(intface("of:0000000000000001", 2),
                                                 intface("of:0000000000000001", 100)) < 0);
        assertTrue(INTERFACES_COMPARATOR.compare(intface("of:0000000000000001", 2),
                                                 intface("of:0000000000000002", 2)) < 0);
    }

    private Interface intface(String deviceID, long port) {
        return new Interface("testInterface", connectPoint1(deviceID, port), null, null, null);
    }

    final ConnectPoint connectPoint1(String deviceID, long portNumber) {
        return new ConnectPoint(DeviceId.deviceId(deviceID), PortNumber.portNumber(portNumber));
    }

    @Test
    public void testDeviceKeyComparator() {
        assertEquals(0, DEVICE_KEY_COMPARATOR.compare(testDK("ID1", "label", "name"),
                                                      testDK("ID1", "label", "name")));
        assertEquals(0, DEVICE_KEY_COMPARATOR.compare(testDK("ID2", "label", "name"),
                                                      testDK("ID2", "label", "name")));
        assertNotEquals(0, DEVICE_KEY_COMPARATOR.compare(testDK("ID1", "label", "name"),
                                                         testDK("ID2", "label", "name")));
    }

    private DeviceKey testDK(String id, String testLabel, String testName) {
        return DeviceKey.createDeviceKeyUsingCommunityName(DeviceKeyId.deviceKeyId(id), testLabel, testName);
    }

    @Test
    public void testRegionComparator() {
        assertEquals(0, REGION_COMPARATOR.compare(region("id1"), region("id1")));
        assertNotEquals(0, REGION_COMPARATOR.compare(region("id1"), region("id2")));
    }

    private Region region(String id) {
        return new DefaultRegion(RegionId.regionId(id), "name", Region.Type.METRO, DefaultAnnotations.EMPTY, null);
    }

    @Test
    public void testTopographicLayoutComparator() {
        assertEquals(0, LAYOUT_COMPARATOR.compare(layout("test"), layout("test")));
        assertNotEquals(0, LAYOUT_COMPARATOR.compare(layout("same"), layout("different")));
    }

    private UiTopoLayout layout(String id) {
        return new UiTopoLayout(UiTopoLayoutId.layoutId(id));
    }

    @Test
    public void testTenantIdComparator() {
        assertEquals(0, TENANT_ID_COMPARATOR.compare(id("1"), id("1")));
        assertEquals(0, TENANT_ID_COMPARATOR.compare(id("tenant1"), id("tenant1")));
        assertNotEquals(0, TENANT_ID_COMPARATOR.compare(id("tenant1"), id("tenant2")));
        assertTrue(TENANT_ID_COMPARATOR.compare(id("1"), id("9")) < 0);
        assertTrue(TENANT_ID_COMPARATOR.compare(id("Tenant5"), id("Tenant0")) > 0);
    }

    private TenantId id(String id) {
        return TenantId.tenantId(id);
    }

}











