/*
 * Copyright 2016-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.lisp.msg.protocols;

import com.google.common.collect.ImmutableList;
import com.google.common.testing.EqualsTester;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.IpAddress;
import org.onosproject.lisp.msg.exceptions.LispParseError;
import org.onosproject.lisp.msg.exceptions.LispReaderException;
import org.onosproject.lisp.msg.exceptions.LispWriterException;
import org.onosproject.lisp.msg.protocols.DefaultLispMapRegister.RegisterReader;
import org.onosproject.lisp.msg.protocols.DefaultLispMapRegister.RegisterWriter;
import org.onosproject.lisp.msg.protocols.LispMapRecord.MapRecordBuilder;
import org.onosproject.lisp.msg.protocols.LispMapRegister.RegisterBuilder;
import org.onosproject.lisp.msg.types.LispIpv4Address;

import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.DefaultMapRecordBuilder;
import static org.onosproject.lisp.msg.protocols.DefaultLispMapRegister.DefaultRegisterBuilder;

/**
 * Unit tests for DefaultLispMapRegister class.
 */
public final class DefaultLispMapRegisterTest {

    private LispMapRegister register1;
    private LispMapRegister sameAsRegister1;
    private LispMapRegister register2;

    @Before
    public void setup() {

        RegisterBuilder builder1 = new DefaultRegisterBuilder();

        List<LispMapRecord> records1 = ImmutableList.of(getMapRecord(), getMapRecord());

        register1 = builder1
                        .withIsProxyMapReply(true)
                        .withIsWantMapNotify(false)
                        .withKeyId((short) 1)
                        .withNonce(1L)
                        .withMapRecords(records1)
                        .build();

        RegisterBuilder builder2 = new DefaultRegisterBuilder();

        List<LispMapRecord> records2 = ImmutableList.of(getMapRecord(), getMapRecord());

        sameAsRegister1 = builder2
                        .withIsProxyMapReply(true)
                        .withIsWantMapNotify(false)
                        .withKeyId((short) 1)
                        .withNonce(1L)
                        .withMapRecords(records2)
                        .build();

        RegisterBuilder builder3 = new DefaultRegisterBuilder();

        register2 = builder3
                        .withIsProxyMapReply(true)
                        .withIsWantMapNotify(false)
                        .withKeyId((short) 2)
                        .withNonce(2L)
                        .build();
    }

    private LispMapRecord getMapRecord() {
        MapRecordBuilder builder1 = new DefaultMapRecordBuilder();

        LispIpv4Address ipv4Locator1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.1"));

        return builder1
                .withRecordTtl(100)
                .withAuthoritative(true)
                .withMapVersionNumber((short) 1)
                .withMaskLength((byte) 0x01)
                .withAction(LispMapReplyAction.NativelyForward)
                .withEidPrefixAfi(ipv4Locator1)
                .build();
    }

    @Test
    public void testEquality() {
        new EqualsTester()
                .addEqualityGroup(register1, sameAsRegister1)
                .addEqualityGroup(register2).testEquals();
    }

    @Test
    public void testConstruction() {
        DefaultLispMapRegister register = (DefaultLispMapRegister) register1;

        assertThat(register.isProxyMapReply(), is(true));
        assertThat(register.isWantMapNotify(), is(false));
        assertThat(register.getKeyId(), is((short) 1));
        assertThat(register.getNonce(), is(1L));
        assertThat(register.getRecordCount(), is(2));
    }

    @Test
    public void testSerialization() throws LispReaderException, LispWriterException, LispParseError {
        ByteBuf byteBuf = Unpooled.buffer();

        RegisterWriter writer = new RegisterWriter();
        writer.writeTo(byteBuf, register1);

        RegisterReader reader = new RegisterReader();
        LispMapRegister deserialized = reader.readFrom(byteBuf);

        new EqualsTester()
                .addEqualityGroup(register1, deserialized).testEquals();
    }
}
