/*
 * Copyright 2015 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.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.GridType;
import org.onosproject.net.HostId;
import org.onosproject.net.IndexedLambda;
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.instructions.Instructions;
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.LambdaConstraint;
import org.onosproject.net.intent.constraint.LatencyConstraint;
import org.onosproject.net.intent.constraint.ObstacleConstraint;
import org.onosproject.net.intent.constraint.WaypointConstraint;
import org.onosproject.net.resource.link.LambdaResource;

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)
                        .ingressPoint(ingress)
                        .egressPoint(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()
                .add(Instructions.modL0Lambda(new IndexedLambda(33)))
                .setMpls(MplsLabel.mplsLabel(44))
                .setOutput(PortNumber.CONTROLLER)
                .setEthDst(MacAddress.BROADCAST)
                .build();

        final List<Constraint> constraints =
                ImmutableList.of(
                        new BandwidthConstraint(Bandwidth.bps(1.0)),
                        new LambdaConstraint(LambdaResource.valueOf(3)),
                        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)
                        .ingressPoint(ingress)
                        .egressPoint(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.ingressPoint().deviceId(), is(did("0000000000000001")));
        assertThat(pointIntent.ingressPoint().port(), is(PortNumber.portNumber(1)));
        assertThat(pointIntent.egressPoint().deviceId(), is(did("0000000000000007")));
        assertThat(pointIntent.egressPoint().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));
    }
}
