/*
 * Copyright 2016-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.onlab.util;

import com.google.common.testing.EqualsTester;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Random;

import static java.lang.Integer.max;
import static java.lang.String.format;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;

public class ImmutableByteSequenceTest {
    public static final int MIN_RAND_FIT_VALUE = 0xf;
    public static final int MAX_RAND_FIT_VALUE = 0x7fffffff;
    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void testCopy() throws Exception {

        byte byteValue = (byte) 1;
        short shortValue = (short) byteValue;
        int intValue = (int) byteValue;
        long longValue = (long) byteValue;
        byte[] arrayValue = new byte[64];
        arrayValue[63] = byteValue;
        ByteBuffer bufferValue = ByteBuffer.allocate(64).put(arrayValue);

        ImmutableByteSequence bsByte = ImmutableByteSequence.copyFrom(byteValue);
        ImmutableByteSequence bsShort = ImmutableByteSequence.copyFrom(shortValue);
        ImmutableByteSequence bsInt = ImmutableByteSequence.copyFrom(intValue);
        ImmutableByteSequence bsLong = ImmutableByteSequence.copyFrom(longValue);
        ImmutableByteSequence bsArray = ImmutableByteSequence.copyFrom(arrayValue);
        ImmutableByteSequence bsBuffer = ImmutableByteSequence.copyFrom(bufferValue);

        assertThat("byte sequence of a byte value must have size 1",
                   bsByte.size(), is(equalTo(1)));
        assertThat("byte sequence of a short value must have size 2",
                   bsShort.size(), is(equalTo(2)));
        assertThat("byte sequence of an int value must have size 4",
                   bsInt.size(), is(equalTo(4)));
        assertThat("byte sequence of a long value must have size 8",
                   bsLong.size(), is(equalTo(8)));
        assertThat("byte sequence of a byte array value must have same size of the array",
                   bsArray.size(), is(equalTo(arrayValue.length)));
        assertThat("byte sequence of a byte buffer value must have same size of the buffer",
                   bsBuffer.size(), is(equalTo(bufferValue.capacity())));

        String errStr = "incorrect byte sequence value";

        assertThat(errStr, bsByte.asArray()[0], is(equalTo(byteValue)));
        assertThat(errStr, bsShort.asArray()[1], is(equalTo(byteValue)));
        assertThat(errStr, bsInt.asArray()[3], is(equalTo(byteValue)));
        assertThat(errStr, bsLong.asArray()[7], is(equalTo(byteValue)));
        assertThat(errStr, bsArray.asArray()[63], is(equalTo(byteValue)));
        assertThat(errStr, bsBuffer.asArray()[63], is(equalTo(byteValue)));
    }

    @Test
    public void testEndianness() throws Exception {

        long longValue = new Random().nextLong();

        // creates a new sequence from a big-endian buffer
        ByteBuffer bbBigEndian = ByteBuffer
                .allocate(8)
                .order(ByteOrder.BIG_ENDIAN)
                .putLong(longValue);
        ImmutableByteSequence bsBufferCopyBigEndian =
                ImmutableByteSequence.copyFrom(bbBigEndian);

        // creates a new sequence from a little-endian buffer
        ByteBuffer bbLittleEndian = ByteBuffer
                .allocate(8)
                .order(ByteOrder.LITTLE_ENDIAN)
                .putLong(longValue);
        ImmutableByteSequence bsBufferCopyLittleEndian =
                ImmutableByteSequence.copyFrom(bbLittleEndian);

        // creates a new sequence from primitive type
        ImmutableByteSequence bsLongCopy =
                ImmutableByteSequence.copyFrom(longValue);


        new EqualsTester()
                // big-endian byte array cannot be equal to little-endian array
                .addEqualityGroup(bbBigEndian.array())
                .addEqualityGroup(bbLittleEndian.array())
                // all byte sequences must be equal
                .addEqualityGroup(bsBufferCopyBigEndian,
                                  bsBufferCopyLittleEndian,
                                  bsLongCopy)
                // byte buffer views of all sequences must be equal
                .addEqualityGroup(bsBufferCopyBigEndian.asReadOnlyBuffer(),
                                  bsBufferCopyLittleEndian.asReadOnlyBuffer(),
                                  bsLongCopy.asReadOnlyBuffer())
                // byte buffer orders of all sequences must be ByteOrder.BIG_ENDIAN
                .addEqualityGroup(bsBufferCopyBigEndian.asReadOnlyBuffer().order(),
                                  bsBufferCopyLittleEndian.asReadOnlyBuffer().order(),
                                  bsLongCopy.asReadOnlyBuffer().order(),
                                  ByteOrder.BIG_ENDIAN)
                .testEquals();
    }

    @Test
    public void testBitSetMethods() throws Exception {
        // All zeros tests
        assertThat("3 bytes, all 0's",
                   ImmutableByteSequence.ofZeros(3),
                   is(equalTo(ImmutableByteSequence.copyFrom(
                           new byte[]{0, 0, 0}))));
        assertThat("3 bytes, all 0's via prefix",
                   ImmutableByteSequence.prefixZeros(3, 3 * Byte.SIZE),
                   is(equalTo(ImmutableByteSequence.copyFrom(
                           new byte[]{0, 0, 0}))));

        // All ones tests
        assertThat("3 bytes, all 1's",
                   ImmutableByteSequence.ofZeros(3),
                   is(equalTo(ImmutableByteSequence.copyFrom(
                           new byte[]{0, 0, 0}))));
        assertThat("3 bytes, all 1's via prefix",
                   ImmutableByteSequence.prefixOnes(3, 3 * Byte.SIZE),
                   is(equalTo(ImmutableByteSequence.copyFrom(
                           new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff}))));

        // Zero prefix tests
        assertThat("2 bytes, prefixed with 5 0's",
                   ImmutableByteSequence.prefix(2, 5, (byte) 0),
                   is(equalTo(ImmutableByteSequence.copyFrom(
                           new byte[]{(byte) 0x7, (byte) 0xff}))));
        assertThat("4 bytes, prefixed with 16 0's",
                   ImmutableByteSequence.prefix(4, 16, (byte) 0),
                   is(equalTo(ImmutableByteSequence.copyFrom(
                           new byte[]{0, 0, (byte) 0xff, (byte) 0xff}))));
        assertThat("4 bytes, prefixed with 20 0's",
                   ImmutableByteSequence.prefix(4, 20, (byte) 0),
                   is(equalTo(ImmutableByteSequence.copyFrom(
                           new byte[]{0, 0, (byte) 0x0f, (byte) 0xff}))));
        assertThat("8 bytes, prefixed with 36 0's",
                   ImmutableByteSequence.prefixZeros(8, 38),
                   is(equalTo(ImmutableByteSequence.copyFrom(
                           new byte[]{0, 0, 0, 0, (byte) 0x03, (byte) 0xff, (byte) 0xff, (byte) 0xff}))));

        // Ones prefix tests
        assertThat("2 bytes, prefixed with 5 1's",
                   ImmutableByteSequence.prefix(2, 5, (byte) 0xff),
                   is(equalTo(ImmutableByteSequence.copyFrom(
                           new byte[]{(byte) 0xf8, 0}))));
        assertThat("4 bytes, prefixed with 16 1's",
                   ImmutableByteSequence.prefix(4, 16, (byte) 0xff),
                   is(equalTo(ImmutableByteSequence.copyFrom(
                           new byte[]{(byte) 0xff, (byte) 0xff, 0, 0}))));
        assertThat("4 bytes, prefixed with 20 1's",
                   ImmutableByteSequence.prefix(4, 20, (byte) 0xff),
                   is(equalTo(ImmutableByteSequence.copyFrom(
                           new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xf0, 0}))));
        assertThat("8 bytes, prefixed with 10 1's",
                   ImmutableByteSequence.prefixOnes(8, 10),
                   is(equalTo(ImmutableByteSequence.copyFrom(
                           new byte[]{(byte) 0xff, (byte) 0xc0, 0, 0, 0, 0, 0, 0}))));
    }

    @Test
    public void testBadPrefixVal() {
        thrown.expect(IllegalArgumentException.class);
        thrown.reportMissingExceptionWithMessage(
                "Expect IllegalArgumentException due to val = 0x7");
        ImmutableByteSequence.prefix(5, 10, (byte) 0x7);
    }

    @Test
    public void testMsbIndex() {
        assertThat("Value 0 should have MSB index -1",
                   ImmutableByteSequence.copyFrom(0).msbIndex(), is(-1));
        for (int i = 0; i < 63; i++) {
            long value = (long) Math.pow(2, i);
            assertThat(format("Value %d should have MSB index %d", value, i),
                       ImmutableByteSequence.copyFrom(value).msbIndex(), is(i));
        }
    }

    private void checkIllegalFit(ImmutableByteSequence bytes, int bitWidth) {
        try {
            ImmutableByteSequence.fit(bytes, bitWidth);
            Assert.fail(format("Except ByteSequenceTrimException due to value = %s and bitWidth %d",
                               bytes.toString(), bitWidth));
        } catch (ImmutableByteSequence.ByteSequenceTrimException e) {
            // We expect this.
        }
    }

    private void checkLegalFit(ImmutableByteSequence bytes, int bitWidth)
            throws ImmutableByteSequence.ByteSequenceTrimException {
        ImmutableByteSequence fitBytes = ImmutableByteSequence.fit(bytes, bitWidth);
        ImmutableByteSequence sameBytes = ImmutableByteSequence.fit(fitBytes, bytes.size() * 8);
        assertThat(format("Fitted value %s (re-extended to %s) not equal to original value %s",
                          fitBytes, sameBytes, bytes),
                   sameBytes,
                   is(equalTo(bytes)));
    }

    @Test
    public void testFit() throws ImmutableByteSequence.ByteSequenceTrimException {
        // Test fit by forcing a given MSB index.
        for (int msbIndex = 0; msbIndex < 32; msbIndex++) {
            long value = (long) Math.pow(2, msbIndex);
            ImmutableByteSequence bytes = ImmutableByteSequence.copyFrom(value);
            checkLegalFit(bytes, msbIndex + 1);
            if (msbIndex != 0) {
                checkIllegalFit(bytes, msbIndex);
            }
        }
    }

    @Test
    public void testRandomFit() throws ImmutableByteSequence.ByteSequenceTrimException {
        // Test fit against the computed MSB index.
        Random random = new Random();
        for (int i = 0; i < 1000; i++) {
            int randValue = random.nextInt((MAX_RAND_FIT_VALUE - MIN_RAND_FIT_VALUE) + 1) + MIN_RAND_FIT_VALUE;
            ImmutableByteSequence bytes = ImmutableByteSequence.copyFrom((long) randValue);
            int msbIndex = bytes.msbIndex();
            // Truncate.
            checkIllegalFit(bytes, max(msbIndex - random.nextInt(16), 1));
            // Expand.
            checkLegalFit(bytes, msbIndex + 2 + random.nextInt(128));
            // Fit to same bit-width of original value.
            checkLegalFit(bytes, msbIndex + 1);
        }
    }
}