/*
* Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
*
* 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 eu.teraflow.policy;

import static org.assertj.core.api.Assertions.assertThat;

import eu.teraflow.policy.context.model.ConstraintCustom;
import eu.teraflow.policy.context.model.ConstraintEndPointLocation;
import eu.teraflow.policy.context.model.ConstraintSchedule;
import eu.teraflow.policy.context.model.ConstraintSlaAvailability;
import eu.teraflow.policy.context.model.ConstraintSlaCapacity;
import eu.teraflow.policy.context.model.ConstraintSlaIsolationLevel;
import eu.teraflow.policy.context.model.ConstraintSlaLatency;
import eu.teraflow.policy.context.model.ConstraintTypeCustom;
import eu.teraflow.policy.context.model.ConstraintTypeEndPointLocation;
import eu.teraflow.policy.context.model.ConstraintTypeSchedule;
import eu.teraflow.policy.context.model.ConstraintTypeSlaAvailability;
import eu.teraflow.policy.context.model.ConstraintTypeSlaCapacity;
import eu.teraflow.policy.context.model.ConstraintTypeSlaIsolationLevel;
import eu.teraflow.policy.context.model.ConstraintTypeSlaLatency;
import eu.teraflow.policy.context.model.EndPointId;
import eu.teraflow.policy.context.model.IsolationLevelEnum;
import eu.teraflow.policy.context.model.Location;
import eu.teraflow.policy.context.model.LocationTypeRegion;
import eu.teraflow.policy.context.model.TopologyId;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;

@QuarkusTest
class ConstraintTypeTest {

    @Test
    void shouldExtractConstraintCustomFromConstraintTypeCustom() {
        final var constraintType = "constraintType";
        final var constraintValue = "constraintValue";

        final var expectedConstraintCustom = new ConstraintCustom(constraintType, constraintValue);
        final var constraintTypeCustom = new ConstraintTypeCustom(expectedConstraintCustom);

        assertThat(constraintTypeCustom.getConstraintType()).isEqualTo(expectedConstraintCustom);
    }

    @Test
    void shouldExtractConstraintEndPointLocationFromConstraintTypeEndPointLocation() {
        final var expectedTopologyId = new TopologyId("contextId", "id");
        final var expectedDeviceId = "expectedDeviceId";
        final var expectedId = "expectedId";
        final var endPointId = new EndPointId(expectedTopologyId, expectedDeviceId, expectedId);

        final var locationType = new LocationTypeRegion("ATH");
        final var location = new Location(locationType);

        final var expectedConstraintEndPointLocation =
                new ConstraintEndPointLocation(endPointId, location);
        final var constraintTypeEndPointLocation =
                new ConstraintTypeEndPointLocation(expectedConstraintEndPointLocation);

        assertThat(constraintTypeEndPointLocation.getConstraintType())
                .isEqualTo(expectedConstraintEndPointLocation);
    }

    @Test
    void shouldExtractConstraintScheduleFromConstraintTypeSchedule() {
        final var startTimestamp = 4.7f;
        final var durationDays = 97.4f;

        final var expectedConstraintSchedule = new ConstraintSchedule(startTimestamp, durationDays);
        final var constraintTypeSchedule = new ConstraintTypeSchedule(expectedConstraintSchedule);

        assertThat(constraintTypeSchedule.getConstraintType()).isEqualTo(expectedConstraintSchedule);
    }

    @Test
    void shouldExtractConstraintSlaAvailabilityFromConstraintTypeSlaAvailability() {
        final var numDisjointPaths = 88;
        final var allActive = false;

        final var expectedConstraintSlaAvailability =
                new ConstraintSlaAvailability(numDisjointPaths, allActive);
        final var constraintTypeSlaAvailability =
                new ConstraintTypeSlaAvailability(expectedConstraintSlaAvailability);

        assertThat(constraintTypeSlaAvailability.getConstraintType())
                .isEqualTo(expectedConstraintSlaAvailability);
    }

    @Test
    void shouldExtractConstraintSlaCapacityFromConstraintTypeSlaCapacity() {
        final var capacityGbps = 0.2f;

        final var expectedConstraintSlaCapacity = new ConstraintSlaCapacity(capacityGbps);
        final var constraintTypeSlaCapacity =
                new ConstraintTypeSlaCapacity(expectedConstraintSlaCapacity);

        assertThat(constraintTypeSlaCapacity.getConstraintType())
                .isEqualTo(expectedConstraintSlaCapacity);
    }

    @Test
    void shouldExtractConstraintSlaIsolationLevelFromConstraintTypeSlaIsolationLevel() {
        final var expectedConstraintSlaIsolationLevel =
                new ConstraintSlaIsolationLevel(IsolationLevelEnum.PHYSICAL_ISOLATION);
        final var constraintTypeSlaIsolationLevel =
                new ConstraintTypeSlaIsolationLevel(expectedConstraintSlaIsolationLevel);

        assertThat(constraintTypeSlaIsolationLevel.getConstraintType())
                .isEqualTo(expectedConstraintSlaIsolationLevel);
    }

    @Test
    void shouldExtractConstraintSlaLatencyFromConstraintTypeSlaLatency() {
        final var capacityGbps = 0.2f;

        final var expectedConstraintSlaLatency = new ConstraintSlaLatency(capacityGbps);
        final var constraintTypeSlaLatency = new ConstraintTypeSlaLatency(expectedConstraintSlaLatency);

        assertThat(constraintTypeSlaLatency.getConstraintType())
                .isEqualTo(expectedConstraintSlaLatency);
    }
}
