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

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.util.Bandwidth;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.core.IdGenerator;
import org.onosproject.net.CltSignalType;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.OduSignalType;
import org.onosproject.net.PortNumber;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.OpticalCircuitIntent;
import org.onosproject.net.intent.OpticalConnectivityIntent;

import static org.junit.Assert.*;

/**
 * Test class for PacketLinkRealizedByOptical class.
 */
public class PacketLinkRealizedByOpticalTest {

    private final ApplicationId appId = new DefaultApplicationId(0, "PacketLinkRealizedByOpticalTest");
    private IdGenerator idGenerator;

    @Before
    public void setUp() {
        idGenerator = new IdGenerator() {
            int counter = 1;

            @Override
            public long getNewId() {
                return counter++;
            }
        };

        Intent.bindIdGenerator(idGenerator);
    }

    @After
    public void tearDown() {
        Intent.unbindIdGenerator(idGenerator);
    }

    /**
     * Checks the construction of PacketLinkRealizedByOptical object with all parameters specified.
     */
    @Test
    public void testCreate() {
        ConnectPoint cp1 = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"), PortNumber.portNumber(1L));
        ConnectPoint cp2 = new ConnectPoint(DeviceId.deviceId("of:0000000000000002"), PortNumber.portNumber(2L));
        Key key = Key.of(10L, appId);
        Bandwidth bandwidth = Bandwidth.bps(100L);

        PacketLinkRealizedByOptical plink = new PacketLinkRealizedByOptical(cp1, cp2, key, bandwidth);

        assertNotNull(plink);
        assertEquals(plink.src(), cp1);
        assertEquals(plink.dst(), cp2);
        assertEquals((long) plink.bandwidth().bps(), 100L);
    }

    /**
     * Checks the construction of OpticalConnectivityId object with OpticalCircuitIntent.
     */
    @Test
    public void testCreateWithCircuitIntent() {
        ConnectPoint cp1 = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"), PortNumber.portNumber(1L));
        ConnectPoint cp2 = new ConnectPoint(DeviceId.deviceId("of:0000000000000002"), PortNumber.portNumber(2L));
        OpticalCircuitIntent circuitIntent = OpticalCircuitIntent.builder()
                .appId(appId)
                .src(cp1)
                .dst(cp2)
                .bidirectional(true)
                .key(Key.of(0, appId))
                .signalType(CltSignalType.CLT_1GBE)
                .build();

        PacketLinkRealizedByOptical plink = PacketLinkRealizedByOptical.create(cp1, cp2, circuitIntent);

        assertNotNull(plink);
        assertEquals(plink.src(), cp1);
        assertEquals(plink.dst(), cp2);
        assertEquals((long) plink.bandwidth().bps(), CltSignalType.CLT_1GBE.bitRate());
    }

    /**
     * Checks the construction of OpticalConnectivityId object with OpticalConnectivityIntent.
     */
    @Test
    public void testCreateWithConnectivityIntent() {
        ConnectPoint cp1 = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"), PortNumber.portNumber(1L));
        ConnectPoint cp2 = new ConnectPoint(DeviceId.deviceId("of:0000000000000002"), PortNumber.portNumber(2L));
        OpticalConnectivityIntent connIntent = OpticalConnectivityIntent.builder()
                .appId(appId)
                .src(cp1)
                .dst(cp2)
                .bidirectional(true)
                .key(Key.of(0, appId))
                .signalType(OduSignalType.ODU4)
                .build();

        PacketLinkRealizedByOptical plink = PacketLinkRealizedByOptical.create(cp1, cp2, connIntent);

        assertNotNull(plink);
        assertEquals(plink.src(), cp1);
        assertEquals(plink.dst(), cp2);
        assertEquals((long) plink.bandwidth().bps(), OduSignalType.ODU4.bitRate());
    }

    /**
     * Checks that isBetween() method works.
     */
    @Test
    public void testIsBetween() {
        ConnectPoint cp1 = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"), PortNumber.portNumber(1L));
        ConnectPoint cp2 = new ConnectPoint(DeviceId.deviceId("of:0000000000000002"), PortNumber.portNumber(2L));
        ConnectPoint cp3 = new ConnectPoint(DeviceId.deviceId("of:0000000000000003"), PortNumber.portNumber(3L));
        OpticalCircuitIntent ochIntent = OpticalCircuitIntent.builder()
                .appId(appId)
                .src(cp1)
                .dst(cp2)
                .bidirectional(true)
                .key(Key.of(0, appId))
                .signalType(CltSignalType.CLT_1GBE)
                .build();

        PacketLinkRealizedByOptical plink = PacketLinkRealizedByOptical.create(cp1, cp2, ochIntent);

        assertTrue(plink.isBetween(cp1, cp2));
        assertFalse(plink.isBetween(cp1, cp3));
    }
}