/*
 * 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.String.format;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;

public class ImmutableByteSequenceTest {
    @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++) {
            ImmutableByteSequence bytes = ImmutableByteSequence.copyFrom((long) Math.abs(random.nextInt()));
            int msbIndex = bytes.msbIndex();
            checkIllegalFit(bytes, msbIndex - random.nextInt(16));
            checkLegalFit(bytes, msbIndex + 2 + random.nextInt(16));
            checkLegalFit(bytes, msbIndex + 1);
        }
    }
}