/*
 * 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.ctl.impl;

import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.IpAddress;
import org.onosproject.lisp.msg.protocols.DefaultLispLocator.DefaultLocatorBuilder;
import org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.DefaultMapRecordBuilder;
import org.onosproject.lisp.msg.protocols.LispEidRecord;
import org.onosproject.lisp.msg.protocols.LispLocator;
import org.onosproject.lisp.msg.protocols.LispMapRecord;
import org.onosproject.lisp.msg.protocols.LispMapRecord.MapRecordBuilder;
import org.onosproject.lisp.msg.types.LispIpv4Address;

import java.util.List;

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

/**
 * Tests for LISP EID RLOC Map class.
 */
public class LispMappingDatabaseTest {

    private static final String LOCATOR_IP_1_1 = "123.1.1.1";
    private static final String LOCATOR_IP_1_2 = "123.1.1.2";
    private static final String LOCATOR_IP_1_3 = "123.1.1.3";

    private static final String LOCATOR_IP_2_1 = "123.2.1.1";
    private static final String LOCATOR_IP_2_2 = "123.2.1.2";

    private static final String LOCATOR_IP_3_1 = "123.3.1.1";

    private static final String EID_IP_1 = "10.1.1.1";
    private static final String EID_IP_2 = "10.1.2.0";
    private static final String EID_IP_3 = "10.2.0.0";

    private static final String EID_IP_PREFIX_1_32 = "10.2.1.1";
    private static final String EID_IP_PREFIX_1_24 = "10.2.1.0";
    private static final String EID_IP_PREFIX_1_16 = "10.2.0.0";

    private static final String EID_IP_PREFIX_2_32 = "10.1.2.1";
    private static final String EID_IP_PREFIX_2_24 = "10.1.2.0";

    final LispMappingDatabase mapDb = LispExpireMapDatabase.getInstance();

    @Before
    public void setup() {

        byte cidr1 = (byte) 32;
        LispIpv4Address eid1 = new LispIpv4Address(IpAddress.valueOf(EID_IP_1));
        LispEidRecord eidRecord1 = new LispEidRecord(cidr1, eid1);

        LispIpv4Address locator11 = new LispIpv4Address(IpAddress.valueOf(LOCATOR_IP_1_1));
        LispIpv4Address locator12 = new LispIpv4Address(IpAddress.valueOf(LOCATOR_IP_1_2));
        LispIpv4Address locator13 = new LispIpv4Address(IpAddress.valueOf(LOCATOR_IP_1_3));

        LispLocator locatorRecord11 = new DefaultLocatorBuilder()
                .withLocatorAfi(locator11).build();
        LispLocator locatorRecord12 = new DefaultLocatorBuilder()
                .withLocatorAfi(locator12).build();
        LispLocator locatorRecord13 = new DefaultLocatorBuilder()
                .withLocatorAfi(locator13).build();
        List<LispLocator> locatorRecords1 =
                ImmutableList.of(locatorRecord11, locatorRecord12, locatorRecord13);

        byte cidr2 = (byte) 24;
        LispIpv4Address eid2 = new LispIpv4Address(IpAddress.valueOf(EID_IP_2));
        LispEidRecord eidRecord2 = new LispEidRecord(cidr2, eid2);

        LispIpv4Address locator21 = new LispIpv4Address(IpAddress.valueOf(LOCATOR_IP_2_1));
        LispIpv4Address locator22 = new LispIpv4Address(IpAddress.valueOf(LOCATOR_IP_2_2));

        LispLocator locatorRecord21 = new DefaultLocatorBuilder()
                .withLocatorAfi(locator21).build();
        LispLocator locatorRecord22 = new DefaultLocatorBuilder()
                .withLocatorAfi(locator22).build();

        List<LispLocator> locatorRecords2 =
                ImmutableList.of(locatorRecord21, locatorRecord22);

        byte cidr3 = (byte) 16;
        LispIpv4Address eid3 = new LispIpv4Address(IpAddress.valueOf(EID_IP_3));
        LispEidRecord eidRecord3 = new LispEidRecord(cidr3, eid3);

        LispIpv4Address locator31 = new LispIpv4Address(IpAddress.valueOf(LOCATOR_IP_3_1));

        LispLocator locatorRecord31 = new DefaultLocatorBuilder()
                .withLocatorAfi(locator31).build();

        List<LispLocator> locatorRecords3 = ImmutableList.of(locatorRecord31);

        MapRecordBuilder builder1 = new DefaultMapRecordBuilder();
        builder1.withMaskLength(cidr1);
        builder1.withEidPrefixAfi(eid1);
        builder1.withLocators(locatorRecords1);
        builder1.withRecordTtl(60);
        LispMapRecord mapRecord1 = builder1.build();

        MapRecordBuilder builder2 = new DefaultMapRecordBuilder();
        builder2.withMaskLength(cidr2);
        builder2.withEidPrefixAfi(eid2);
        builder2.withLocators(locatorRecords2);
        builder2.withRecordTtl(60);
        LispMapRecord mapRecord2 = builder2.build();

        MapRecordBuilder builder3 = new DefaultMapRecordBuilder();
        builder3.withMaskLength(cidr3);
        builder3.withEidPrefixAfi(eid3);
        builder3.withLocators(locatorRecords3);
        builder3.withRecordTtl(60);
        LispMapRecord mapRecord3 = builder3.build();

        mapDb.putMapRecord(eidRecord1, mapRecord1, true);
        mapDb.putMapRecord(eidRecord2, mapRecord2, true);
        mapDb.putMapRecord(eidRecord3, mapRecord3, true);
    }

    @Test
    public void test32MaskRange() {
        byte cidr32 = (byte) 32;
        LispIpv4Address eid = new LispIpv4Address(IpAddress.valueOf(EID_IP_1));
        LispEidRecord record = new LispEidRecord(cidr32, eid);
        LispMapRecord mapRecord = mapDb.getMapRecordByEidRecord(record, true);

        assertThat("Failed to fetch the RLOCs with /32 EID record",
                mapRecord.getLocatorCount(), is(3));
    }

    @Test
    public void test24MaskRange() {
        byte cidr32 = (byte) 32;
        LispIpv4Address eid = new LispIpv4Address(IpAddress.valueOf(EID_IP_PREFIX_2_32));
        LispEidRecord record32 = new LispEidRecord(cidr32, eid);
        LispMapRecord mapRecord32 = mapDb.getMapRecordByEidRecord(record32, true);

        byte cidr24 = (byte) 24;
        LispIpv4Address eid24 = new LispIpv4Address(IpAddress.valueOf(EID_IP_PREFIX_2_24));
        LispEidRecord record24 = new LispEidRecord(cidr24, eid24);
        LispMapRecord mapRecord24 = mapDb.getMapRecordByEidRecord(record24, true);

        assertThat("Failed to fetch the RLOCs with /32 EID record",
                mapRecord32.getLocatorCount(), is(2));
        assertThat("Failed to fetch the RLOCs with /24 EID record",
                mapRecord24.getLocatorCount(), is(2));
    }

    @Test
    public void test16MaskRange() {
        byte cidr32 = (byte) 32;
        LispIpv4Address eid = new LispIpv4Address(IpAddress.valueOf(EID_IP_PREFIX_1_32));
        LispEidRecord record32 = new LispEidRecord(cidr32, eid);
        LispMapRecord mapRecord32 = mapDb.getMapRecordByEidRecord(record32, true);

        byte cidr24 = (byte) 24;
        LispIpv4Address eid24 = new LispIpv4Address(IpAddress.valueOf(EID_IP_PREFIX_1_24));
        LispEidRecord record24 = new LispEidRecord(cidr24, eid24);
        LispMapRecord mapRecord24 = mapDb.getMapRecordByEidRecord(record24, true);

        byte cidr16 = (byte) 16;
        LispIpv4Address eid16 = new LispIpv4Address(IpAddress.valueOf(EID_IP_PREFIX_1_16));
        LispEidRecord record16 = new LispEidRecord(cidr16, eid16);
        LispMapRecord mapRecord16 = mapDb.getMapRecordByEidRecord(record16, true);

        assertThat("Failed to fetch the RLOCs with /32 EID record",
                mapRecord32.getLocatorCount(), is(1));
        assertThat("Failed to fetch the RLOCs with /24 EID record",
                mapRecord24.getLocatorCount(), is(1));
        assertThat("Failed to fetch the RLOCs with /16 EID record",
                mapRecord16.getLocatorCount(), is(1));
    }
}
