/*
 * Copyright 2017-present 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.drivers.lisp.extensions.codec;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableList;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeDiagnosingMatcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.IpPrefix;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.drivers.lisp.extensions.LispMappingExtensionCodecRegistrator;
import org.onosproject.drivers.lisp.extensions.LispNatAddress;
import org.onosproject.mapping.addresses.MappingAddress;
import org.onosproject.mapping.addresses.MappingAddresses;
import org.onosproject.mapping.web.codec.MappingAddressJsonMatcher;

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

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;

/**
 * Unit tests for LispNatAddressCodec.
 */
public class LispNatAddressCodecTest {

    private static final short MS_UDP_PORT_NUMBER = (short) 1;
    private static final short ETR_UDP_PORT_NUMBER = (short) 2;
    private static final IpPrefix GLOBAL_ETR_RLOC_ADDRESS = IpPrefix.valueOf("10.1.1.1/24");
    private static final IpPrefix MS_RLOC_ADDRESS = IpPrefix.valueOf("10.1.1.2/24");
    private static final IpPrefix PRIVATE_ETR_RLOC_ADDRESS = IpPrefix.valueOf("10.1.1.3/24");

    private CodecContext context;
    private JsonCodec<LispNatAddress> natAddressCodec;
    private LispMappingExtensionCodecRegistrator registrator;

    /**
     * Sets up for each test.
     * Creates a context and fetches the LispNatAddress codec.
     */
    @Before
    public void setUp() {
        CodecManager manager = new CodecManager();
        registrator = new LispMappingExtensionCodecRegistrator();
        registrator.codecService = manager;
        registrator.activate();

        context = new LispMappingExtensionCodecContextAdapter(registrator.codecService);
        natAddressCodec = context.codec(LispNatAddress.class);
        assertThat("NAT address codec should not be null",
                natAddressCodec, notNullValue());
    }

    /**
     * Deactivates the codec registrator.
     */
    @After
    public void tearDown() {
        registrator.deactivate();
    }

    /**
     * Tests encoding of a LispNatAddress object.
     */
    @Test
    public void testLispNatAddressEncode() {

        List<MappingAddress> rtrRlocs =
                ImmutableList.of(MappingAddresses.ipv4MappingAddress(GLOBAL_ETR_RLOC_ADDRESS),
                        MappingAddresses.ipv4MappingAddress(MS_RLOC_ADDRESS),
                        MappingAddresses.ipv4MappingAddress(PRIVATE_ETR_RLOC_ADDRESS));


        LispNatAddress address = new LispNatAddress.Builder()
                .withMsUdpPortNumber(MS_UDP_PORT_NUMBER)
                .withEtrUdpPortNumber(ETR_UDP_PORT_NUMBER)
                .withGlobalEtrRlocAddress(MappingAddresses.ipv4MappingAddress(GLOBAL_ETR_RLOC_ADDRESS))
                .withMsRlocAddress(MappingAddresses.ipv4MappingAddress(MS_RLOC_ADDRESS))
                .withPrivateEtrRlocAddress(MappingAddresses.ipv4MappingAddress(PRIVATE_ETR_RLOC_ADDRESS))
                .withRtrRlocAddresses(rtrRlocs)
                .build();

        ObjectNode addressJson = natAddressCodec.encode(address, context);
        assertThat("errors in encoding NAT address JSON",
                addressJson, LispNatAddressJsonMatcher.matchesNatAddress(address));
    }

    /**
     * Tests decoding of a LispNatAddress JSON object.
     */
    @Test
    public void testLispNatAddressDecode() throws IOException {
        LispNatAddress address = getLispNatAddress("LispNatAddress.json");

        assertThat("incorrect MS UDP port number",
                address.getMsUdpPortNumber(), is(MS_UDP_PORT_NUMBER));
        assertThat("incorrect ETR UDP port number",
                address.getEtrUdpPortNumber(), is(ETR_UDP_PORT_NUMBER));
        assertThat("incorrect global ETR RLOC address", address.getGlobalEtrRlocAddress(),
                is(MappingAddresses.ipv4MappingAddress(GLOBAL_ETR_RLOC_ADDRESS)));
        assertThat("incorrect MS RLOC address", address.getMsRlocAddress(),
                is(MappingAddresses.ipv4MappingAddress(MS_RLOC_ADDRESS)));
        assertThat("incorrect private ETR RLOC address", address.getPrivateEtrRlocAddress(),
                is(MappingAddresses.ipv4MappingAddress(PRIVATE_ETR_RLOC_ADDRESS)));
    }

    /**
     * Hamcrest matcher for LispNatAddress.
     */
    public static final class LispNatAddressJsonMatcher
            extends TypeSafeDiagnosingMatcher<JsonNode> {

        private final LispNatAddress address;

        /**
         * Default constructor.
         *
         * @param address LispNatAddress object
         */
        private LispNatAddressJsonMatcher(LispNatAddress address) {
            this.address = address;
        }

        private int filteredSize(JsonNode node) {
            return node.size();
        }

        @Override
        protected boolean matchesSafely(JsonNode jsonNode, Description description) {

            // check MS UDP port number
            short jsonMsUdpPortNumber = (short)
                    jsonNode.get(LispNatAddressCodec.MS_UDP_PORT_NUMBER).asInt();
            short msUdpPortNumber = address.getMsUdpPortNumber();
            if (jsonMsUdpPortNumber != msUdpPortNumber) {
                description.appendText("MS UDP port number was " + jsonMsUdpPortNumber);
                return false;
            }

            // check ETR UDP port number
            short jsonEtrUdpPortNumber = (short)
                    jsonNode.get(LispNatAddressCodec.ETR_UDP_PORT_NUMBER).asInt();
            short etrUdpPortNumber = address.getEtrUdpPortNumber();
            if (jsonEtrUdpPortNumber != etrUdpPortNumber) {
                description.appendText("ETR UDP port number was " + jsonEtrUdpPortNumber);
                return false;
            }

            // check RTR RLOC addresses
            final JsonNode jsonRtrRlocs = jsonNode.get(LispNatAddressCodec.RTR_RLOC_ADDRESSES);

            if (address.getRtrRlocAddresses().size() != filteredSize(jsonRtrRlocs)) {
                description.appendText("addresses array size of " +
                        Integer.toString(address.getRtrRlocAddresses().size()));
                return false;
            }

            for (final MappingAddress address : address.getRtrRlocAddresses()) {
                boolean addressFound = false;
                for (int addressIndex = 0; addressIndex < jsonRtrRlocs.size(); addressIndex++) {
                    final String jsonType =
                            jsonRtrRlocs.get(addressIndex).get("type").asText();
                    final String addressType = address.type().name();
                    if (jsonType.equals(addressType)) {
                        addressFound = true;
                    }
                }
                if (!addressFound) {
                    description.appendText("address " + address.toString());
                    return false;
                }
            }

            // check global ETR RLOC address
            MappingAddressJsonMatcher globalEtrRlocMatcher =
                    MappingAddressJsonMatcher.matchesMappingAddress(
                            address.getGlobalEtrRlocAddress());

            // check MS RLOC address
            MappingAddressJsonMatcher msRlocMatcher =
                    MappingAddressJsonMatcher.matchesMappingAddress(
                            address.getMsRlocAddress());

            // check private ETR RLOC address
            MappingAddressJsonMatcher privateEtrRlocMatcher =
                    MappingAddressJsonMatcher.matchesMappingAddress(
                            address.getPrivateEtrRlocAddress());

            return globalEtrRlocMatcher.matches(jsonNode.get(LispNatAddressCodec.GLOBAL_ETR_RLOC_ADDRESS)) ||
                    msRlocMatcher.matches(jsonNode.get(LispNatAddressCodec.MS_RLOC_ADDRESS)) ||
                    privateEtrRlocMatcher.matches(jsonNode.get(LispNatAddressCodec.PRIVATE_ETR_RLOC_ADDRESS));
        }

        @Override
        public void describeTo(Description description) {
            description.appendText(address.toString());
        }

        /**
         * Factory to allocate a LispNatAddress matcher.
         *
         * @param address LispNatAddress object we are looking for
         * @return matcher
         */
        public static LispNatAddressJsonMatcher matchesNatAddress(LispNatAddress address) {
            return new LispNatAddressJsonMatcher(address);
        }
    }

    /**
     * Reads in a LispNatAddress from the given resource and decodes it.
     *
     * @param resourceName resource to use to read the JSON for the rule
     * @return decoded LispGcAddress
     * @throws IOException if processing the resource fails
     */
    private LispNatAddress getLispNatAddress(String resourceName) throws IOException {
        InputStream jsonStream = LispNatAddressCodecTest.class.getResourceAsStream(resourceName);
        JsonNode json = context.mapper().readTree(jsonStream);
        assertThat("JSON string should not be null", json, notNullValue());
        LispNatAddress natAddress = natAddressCodec.decode((ObjectNode) json, context);
        assertThat("decoded address should not be null", natAddress, notNullValue());
        return natAddress;
    }
}
