/*
 * Copyright 2015-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.codec.impl;

import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.util.Bandwidth;
import org.onosproject.codec.JsonCodec;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.FilteredConnectPoint;
import org.onosproject.net.GridType;
import org.onosproject.net.HostId;
import org.onosproject.net.Lambda;
import org.onosproject.net.NetTestTools;
import org.onosproject.net.OchSignalType;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.intent.AbstractIntentTest;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.HostToHostIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentServiceAdapter;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.net.intent.constraint.AnnotationConstraint;
import org.onosproject.net.intent.constraint.AsymmetricPathConstraint;
import org.onosproject.net.intent.constraint.BandwidthConstraint;
import org.onosproject.net.intent.constraint.LatencyConstraint;
import org.onosproject.net.intent.constraint.ObstacleConstraint;
import org.onosproject.net.intent.constraint.WaypointConstraint;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableList;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.onosproject.codec.impl.IntentJsonMatcher.matchesIntent;
import static org.onosproject.net.NetTestTools.did;
import static org.onosproject.net.NetTestTools.hid;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;

/**
 * Unit tests for the host to host intent class codec.
 */
public class IntentCodecTest extends AbstractIntentTest {

    private final HostId id1 = hid("12:34:56:78:91:ab/1");
    private final HostId id2 = hid("12:34:56:78:92:ab/1");
    private final ApplicationId appId = new DefaultApplicationId(3, "test");
    final TrafficSelector emptySelector =
            DefaultTrafficSelector.emptySelector();
    final TrafficTreatment emptyTreatment =
            DefaultTrafficTreatment.emptyTreatment();
    private final MockCodecContext context = new MockCodecContext();
    final CoreService mockCoreService = createMock(CoreService.class);

    @Before
    public void setUpIntentService() {
        final IntentService mockIntentService = new IntentServiceAdapter();
        context.registerService(IntentService.class, mockIntentService);
        context.registerService(CoreService.class, mockCoreService);
        expect(mockCoreService.getAppId(appId.name()))
                .andReturn(appId);
        replay(mockCoreService);
    }

    /**
     * Tests the encoding of a host to host intent.
     */
    @Test
    public void hostToHostIntent() {
        final HostToHostIntent intent =
                HostToHostIntent.builder()
                        .appId(appId)
                        .one(id1)
                        .two(id2)
                        .build();

        final JsonCodec<HostToHostIntent> intentCodec =
                context.codec(HostToHostIntent.class);
        assertThat(intentCodec, notNullValue());

        final ObjectNode intentJson = intentCodec.encode(intent, context);
        assertThat(intentJson, matchesIntent(intent));
    }

    /**
     * Tests the encoding of a point to point intent.
     */
    @Test
    public void pointToPointIntent() {
        ConnectPoint ingress = NetTestTools.connectPoint("ingress", 1);
        ConnectPoint egress = NetTestTools.connectPoint("egress", 2);

        final PointToPointIntent intent =
                PointToPointIntent.builder()
                        .appId(appId)
                        .selector(emptySelector)
                        .treatment(emptyTreatment)
                        .filteredIngressPoint(new FilteredConnectPoint(ingress))
                        .filteredEgressPoint(new FilteredConnectPoint(egress))
                        .build();

        final JsonCodec<PointToPointIntent> intentCodec =
                context.codec(PointToPointIntent.class);
        assertThat(intentCodec, notNullValue());

        final ObjectNode intentJson = intentCodec.encode(intent, context);
        assertThat(intentJson, matchesIntent(intent));
    }

    /**
     * Tests the encoding of an intent with treatment, selector and constraints
     * specified.
     */
    @Test
    public void intentWithTreatmentSelectorAndConstraints() {
        ConnectPoint ingress = NetTestTools.connectPoint("ingress", 1);
        ConnectPoint egress = NetTestTools.connectPoint("egress", 2);
        DeviceId did1 = did("device1");
        DeviceId did2 = did("device2");
        DeviceId did3 = did("device3");
        Lambda ochSignal = Lambda.ochSignal(GridType.DWDM, ChannelSpacing.CHL_100GHZ, 4, 8);
        final TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchIPProtocol((byte) 3)
                .matchMplsLabel(MplsLabel.mplsLabel(4))
                .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID))
                .add(Criteria.matchLambda(ochSignal))
                .matchEthDst(MacAddress.BROADCAST)
                .matchIPDst(IpPrefix.valueOf("1.2.3.4/24"))
                .build();
        final TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                .setMpls(MplsLabel.mplsLabel(44))
                .setOutput(PortNumber.CONTROLLER)
                .setEthDst(MacAddress.BROADCAST)
                .build();

        final List<Constraint> constraints =
                ImmutableList.of(
                        new BandwidthConstraint(Bandwidth.bps(1.0)),
                        new AnnotationConstraint("key", 33.0),
                        new AsymmetricPathConstraint(),
                        new LatencyConstraint(Duration.ofSeconds(2)),
                        new ObstacleConstraint(did1, did2),
                        new WaypointConstraint(did3));

        final PointToPointIntent intent =
                PointToPointIntent.builder()
                        .appId(appId)
                        .selector(selector)
                        .treatment(treatment)
                        .filteredIngressPoint(new FilteredConnectPoint(ingress))
                        .filteredEgressPoint(new FilteredConnectPoint(egress))
                        .constraints(constraints)
                        .build();


        final JsonCodec<PointToPointIntent> intentCodec =
                context.codec(PointToPointIntent.class);
        assertThat(intentCodec, notNullValue());

        final ObjectNode intentJson = intentCodec.encode(intent, context);
        assertThat(intentJson, matchesIntent(intent));

    }

    /**
     * Reads in a rule from the given resource and decodes it.
     *
     * @param resourceName resource to use to read the JSON for the rule
     * @return decoded flow rule
     * @throws IOException if processing the resource fails
     */
    private Intent getIntent(String resourceName, JsonCodec intentCodec) throws IOException {
        InputStream jsonStream = IntentCodecTest.class
                .getResourceAsStream(resourceName);
        JsonNode json = context.mapper().readTree(jsonStream);
        assertThat(json, notNullValue());
        Intent intent = (Intent) intentCodec.decode((ObjectNode) json, context);
        assertThat(intent, notNullValue());
        return intent;
    }

    /**
     * Tests the point to point intent JSON codec.
     *
     * @throws IOException if JSON processing fails
     */
    @Test
    public void decodePointToPointIntent() throws IOException {
        JsonCodec<Intent> intentCodec = context.codec(Intent.class);
        assertThat(intentCodec, notNullValue());

        Intent intent = getIntent("PointToPointIntent.json", intentCodec);
        assertThat(intent, notNullValue());
        assertThat(intent, instanceOf(PointToPointIntent.class));

        PointToPointIntent pointIntent = (PointToPointIntent) intent;
        assertThat(pointIntent.priority(), is(55));
        assertThat(pointIntent.filteredIngressPoint().connectPoint().deviceId(), is(did("0000000000000001")));
        assertThat(pointIntent.filteredIngressPoint().connectPoint().port(), is(PortNumber.portNumber(1)));
        assertThat(pointIntent.filteredEgressPoint().connectPoint().deviceId(), is(did("0000000000000007")));
        assertThat(pointIntent.filteredEgressPoint().connectPoint().port(), is(PortNumber.portNumber(2)));

        assertThat(pointIntent.constraints(), hasSize(1));

        assertThat(pointIntent.selector(), notNullValue());
        assertThat(pointIntent.selector().criteria(), hasSize(1));
        Criterion criterion1 = pointIntent.selector().criteria().iterator().next();
        assertThat(criterion1, instanceOf(EthCriterion.class));
        EthCriterion ethCriterion = (EthCriterion) criterion1;
        assertThat(ethCriterion.mac().toString(), is("11:22:33:44:55:66"));
        assertThat(ethCriterion.type().name(), is("ETH_DST"));

        assertThat(pointIntent.treatment(), notNullValue());
        assertThat(pointIntent.treatment().allInstructions(), hasSize(1));
        Instruction instruction1 = pointIntent.treatment().allInstructions().iterator().next();
        assertThat(instruction1, instanceOf(ModEtherInstruction.class));
        ModEtherInstruction ethInstruction = (ModEtherInstruction) instruction1;
        assertThat(ethInstruction.mac().toString(), is("22:33:44:55:66:77"));
        assertThat(ethInstruction.type().toString(), is("L2MODIFICATION"));
        assertThat(ethInstruction.subtype().toString(), is("ETH_SRC"));
    }

    /**
     * Tests the host to host intent JSON codec.
     *
     * @throws IOException
     */
    @Test
    public void decodeHostToHostIntent() throws IOException {
        JsonCodec<Intent> intentCodec = context.codec(Intent.class);
        assertThat(intentCodec, notNullValue());

        Intent intent = getIntent("HostToHostIntent.json", intentCodec);
        assertThat(intent, notNullValue());
        assertThat(intent, instanceOf(HostToHostIntent.class));

        HostToHostIntent hostIntent = (HostToHostIntent) intent;
        assertThat(hostIntent.priority(), is(7));
        assertThat(hostIntent.constraints(), hasSize(1));
    }
}
