/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.activemq.artemis.utils;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ReadOnlyBufferException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;

import io.netty.util.internal.PlatformDependent;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class ByteUtilTest {

   private static Logger log = Logger.getLogger(ByteUtilTest.class);

   @Test
   public void testBytesToString() {
      byte[] byteArray = new byte[]{0, 1, 2, 3};

      testEquals("0001 0203", ByteUtil.bytesToHex(byteArray, 2));
      testEquals("00 01 02 03", ByteUtil.bytesToHex(byteArray, 1));
      testEquals("000102 03", ByteUtil.bytesToHex(byteArray, 3));
   }

   @Test
   public void testNonASCII() {
      assertEquals("aA", ByteUtil.toSimpleString(new byte[]{97, 0, 65, 0}));
      assertEquals(ByteUtil.NON_ASCII_STRING, ByteUtil.toSimpleString(new byte[]{0, 97, 0, 65}));
      log.debug(ByteUtil.toSimpleString(new byte[]{0, 97, 0, 65}));
   }

   @Test
   public void testMaxString() {
      byte[] byteArray = new byte[20 * 1024];
      log.debug(ByteUtil.maxString(ByteUtil.bytesToHex(byteArray, 2), 150));
   }

   void testEquals(String string1, String string2) {
      if (!string1.equals(string2)) {
         Assert.fail("String are not the same:=" + string1 + "!=" + string2);
      }
   }

   @Test
   public void testTextBytesToLongBytes() {
      long[] factor = new long[] {1, 5, 10};
      String[] type = new String[]{"", "b", "k", "m", "g"};
      long[] size = new long[]{1, 1, 1024, 1024 * 1024, 1024 * 1024 * 1024};

      for (int i = 0; i < 3; i++) {
         for (int j = 0; j < type.length; j++) {
            assertEquals(factor[i] * size[j], ByteUtil.convertTextBytes(factor[i] + type[j]));
            assertEquals(factor[i] * size[j], ByteUtil.convertTextBytes(factor[i] + " " + type[j]));
            assertEquals(factor[i] * size[j], ByteUtil.convertTextBytes(factor[i] + type[j].toUpperCase()));
            assertEquals(factor[i] * size[j], ByteUtil.convertTextBytes(factor[i] + " " + type[j].toUpperCase()));
            if (j >= 2) {
               assertEquals(factor[i] * size[j], ByteUtil.convertTextBytes(factor[i] + type[j] + "b"));
               assertEquals(factor[i] * size[j], ByteUtil.convertTextBytes(factor[i] + " " + type[j] + "b"));
               assertEquals(factor[i] * size[j], ByteUtil.convertTextBytes(factor[i] + type[j].toUpperCase() + "B"));
               assertEquals(factor[i] * size[j], ByteUtil.convertTextBytes(factor[i] + " " + type[j].toUpperCase() + "B"));
            }
         }
      }
   }

   @Test
   public void testUnsafeUnalignedByteArrayHashCode() {
      Assume.assumeTrue(PlatformDependent.hasUnsafe());
      Assume.assumeTrue(PlatformDependent.isUnaligned());
      Map<byte[], Integer> map = new LinkedHashMap<>();
      map.put(new byte[0], 1);
      map.put(new byte[]{1}, 32);
      map.put(new byte[]{2}, 33);
      map.put(new byte[]{0, 1}, 962);
      map.put(new byte[]{1, 2}, 994);
      if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
         map.put(new byte[]{0, 1, 2, 3, 4, 5}, 63504931);
         map.put(new byte[]{6, 7, 8, 9, 0, 1}, -1603953111);
         map.put(new byte[]{-1, -1, -1, (byte) 0xE1}, 1);
      } else {
         map.put(new byte[]{0, 1, 2, 3, 4, 5}, 1250309600);
         map.put(new byte[]{6, 7, 8, 9, 0, 1}, -417148442);
         map.put(new byte[]{-1, -1, -1, (byte) 0xE1}, -503316450);
      }
      for (Map.Entry<byte[], Integer> e : map.entrySet()) {
         assertEquals("input = " + Arrays.toString(e.getKey()), e.getValue().intValue(), ByteUtil.hashCode(e.getKey()));
      }
   }

   @Test
   public void testNoUnsafeAlignedByteArrayHashCode() {
      Assume.assumeFalse(PlatformDependent.hasUnsafe());
      Assume.assumeFalse(PlatformDependent.isUnaligned());
      ArrayList<byte[]> inputs = new ArrayList<>();
      inputs.add(new byte[0]);
      inputs.add(new byte[]{1});
      inputs.add(new byte[]{2});
      inputs.add(new byte[]{0, 1});
      inputs.add(new byte[]{1, 2});
      inputs.add(new byte[]{0, 1, 2, 3, 4, 5});
      inputs.add(new byte[]{6, 7, 8, 9, 0, 1});
      inputs.add(new byte[]{-1, -1, -1, (byte) 0xE1});
      inputs.forEach(input -> assertEquals("input = " + Arrays.toString(input), Arrays.hashCode(input), ByteUtil.hashCode(input)));
   }

   @Test
   public void testTextBytesToLongBytesNegative() {
      try {
         ByteUtil.convertTextBytes("x");
         fail();
      } catch (Exception e) {
         assertTrue(e instanceof IllegalArgumentException);
      }
   }

   private static byte[] duplicateRemaining(ByteBuffer buffer, int offset, int bytes) {
      final int end = offset + bytes;
      final int expectedRemaining = buffer.capacity() - end;
      //it is handling the case of <0 just to allow from to > capacity
      if (expectedRemaining <= 0) {
         return null;
      }
      final byte[] remaining = new byte[expectedRemaining];
      final ByteBuffer duplicate = buffer.duplicate();
      duplicate.clear().position(end);
      duplicate.get(remaining, 0, expectedRemaining);
      return remaining;
   }

   private static byte[] duplicateBefore(ByteBuffer buffer, int offset) {
      if (offset <= 0) {
         return null;
      }
      final int size = Math.min(buffer.capacity(), offset);
      final byte[] remaining = new byte[size];
      final ByteBuffer duplicate = buffer.duplicate();
      duplicate.clear();
      duplicate.get(remaining, 0, size);
      return remaining;
   }

   private static void shouldZeroesByteBuffer(ByteBuffer buffer, int offset, int bytes) {
      final byte[] originalBefore = duplicateBefore(buffer, offset);
      final byte[] originalRemaining = duplicateRemaining(buffer, offset, bytes);
      final int position = buffer.position();
      final int limit = buffer.limit();
      ByteUtil.zeros(buffer, offset, bytes);
      Assert.assertEquals(position, buffer.position());
      Assert.assertEquals(limit, buffer.limit());
      final byte[] zeros = new byte[bytes];
      final byte[] content = new byte[bytes];
      final ByteBuffer duplicate = buffer.duplicate();
      duplicate.clear().position(offset);
      duplicate.get(content, 0, bytes);
      Assert.assertArrayEquals(zeros, content);
      if (originalRemaining != null) {
         final byte[] remaining = new byte[duplicate.remaining()];
         //duplicate position has been moved of bytes
         duplicate.get(remaining);
         Assert.assertArrayEquals(originalRemaining, remaining);
      }
      if (originalBefore != null) {
         final byte[] before = new byte[offset];
         //duplicate position has been moved of bytes: need to reset it
         duplicate.position(0);
         duplicate.get(before);
         Assert.assertArrayEquals(originalBefore, before);
      }
   }

   private ByteBuffer fill(ByteBuffer buffer, int offset, int length, byte value) {
      for (int i = 0; i < length; i++) {
         buffer.put(offset + i, value);
      }
      return buffer;
   }

   @Test
   public void shouldZeroesDirectByteBuffer() {
      final byte one = (byte) 1;
      final int capacity = 64;
      final int bytes = 32;
      final int offset = 1;
      final ByteBuffer buffer = ByteBuffer.allocateDirect(capacity);
      try {
         fill(buffer, 0, capacity, one);
         shouldZeroesByteBuffer(buffer, offset, bytes);
      } finally {
         if (PlatformDependent.hasUnsafe()) {
            PlatformDependent.freeDirectBuffer(buffer);
         }
      }
   }

   @Test
   public void shouldZeroesLimitedDirectByteBuffer() {
      final byte one = (byte) 1;
      final int capacity = 64;
      final int bytes = 32;
      final int offset = 1;
      final ByteBuffer buffer = ByteBuffer.allocateDirect(capacity);
      try {
         fill(buffer, 0, capacity, one);
         buffer.limit(0);
         shouldZeroesByteBuffer(buffer, offset, bytes);
      } finally {
         if (PlatformDependent.hasUnsafe()) {
            PlatformDependent.freeDirectBuffer(buffer);
         }
      }
   }

   @Test
   public void shouldZeroesHeapByteBuffer() {
      final byte one = (byte) 1;
      final int capacity = 64;
      final int bytes = 32;
      final int offset = 1;
      final ByteBuffer buffer = ByteBuffer.allocate(capacity);
      fill(buffer, 0, capacity, one);
      shouldZeroesByteBuffer(buffer, offset, bytes);
   }

   @Test
   public void shouldZeroesLimitedHeapByteBuffer() {
      final byte one = (byte) 1;
      final int capacity = 64;
      final int bytes = 32;
      final int offset = 1;
      final ByteBuffer buffer = ByteBuffer.allocate(capacity);
      fill(buffer, 0, capacity, one);
      buffer.limit(0);
      shouldZeroesByteBuffer(buffer, offset, bytes);
   }

   @Test(expected = ReadOnlyBufferException.class)
   public void shouldFailWithReadOnlyHeapByteBuffer() {
      final byte one = (byte) 1;
      final int capacity = 64;
      final int bytes = 32;
      final int offset = 1;
      ByteBuffer buffer = ByteBuffer.allocate(capacity);
      fill(buffer, 0, capacity, one);
      buffer = buffer.asReadOnlyBuffer();
      shouldZeroesByteBuffer(buffer, offset, bytes);
   }

   @Test(expected = IndexOutOfBoundsException.class)
   public void shouldFailIfOffsetIsGreaterOrEqualHeapByteBufferCapacity() {
      final byte one = (byte) 1;
      final int capacity = 64;
      final int bytes = 0;
      final int offset = 64;
      ByteBuffer buffer = ByteBuffer.allocate(capacity);
      fill(buffer, 0, capacity, one);
      try {
         shouldZeroesByteBuffer(buffer, offset, bytes);
      } catch (IndexOutOfBoundsException expectedEx) {
         //verify that the buffer hasn't changed
         final byte[] originalContent = duplicateRemaining(buffer, 0, 0);
         final byte[] expectedContent = new byte[capacity];
         Arrays.fill(expectedContent, one);
         Assert.assertArrayEquals(expectedContent, originalContent);
         throw expectedEx;
      }
   }

   @Test(expected = IllegalArgumentException.class)
   public void shouldFailIfOffsetIsNegative() {
      final byte one = (byte) 1;
      final int capacity = 64;
      final int bytes = 1;
      final int offset = -1;
      ByteBuffer buffer = ByteBuffer.allocate(capacity);
      fill(buffer, 0, capacity, one);
      try {
         shouldZeroesByteBuffer(buffer, offset, bytes);
      } catch (IndexOutOfBoundsException expectedEx) {
         //verify that the buffer hasn't changed
         final byte[] originalContent = duplicateRemaining(buffer, 0, 0);
         final byte[] expectedContent = new byte[capacity];
         Arrays.fill(expectedContent, one);
         Assert.assertArrayEquals(expectedContent, originalContent);
         throw expectedEx;
      }
   }

   @Test(expected = IllegalArgumentException.class)
   public void shouldFailIfBytesIsNegative() {
      final byte one = (byte) 1;
      final int capacity = 64;
      final int bytes = -1;
      final int offset = 0;
      ByteBuffer buffer = ByteBuffer.allocate(capacity);
      fill(buffer, 0, capacity, one);
      try {
         shouldZeroesByteBuffer(buffer, offset, bytes);
      } catch (IndexOutOfBoundsException expectedEx) {
         //verify that the buffer hasn't changed
         final byte[] originalContent = duplicateRemaining(buffer, 0, 0);
         final byte[] expectedContent = new byte[capacity];
         Arrays.fill(expectedContent, one);
         Assert.assertArrayEquals(expectedContent, originalContent);
         throw expectedEx;
      }
   }

   @Test(expected = IndexOutOfBoundsException.class)
   public void shouldFailIfExceedingHeapByteBufferCapacity() {
      final byte one = (byte) 1;
      final int capacity = 64;
      final int bytes = 65;
      final int offset = 1;
      ByteBuffer buffer = ByteBuffer.allocate(capacity);
      fill(buffer, 0, capacity, one);
      try {
         shouldZeroesByteBuffer(buffer, offset, bytes);
      } catch (IndexOutOfBoundsException expectedEx) {
         //verify that the buffer hasn't changed
         final byte[] originalContent = duplicateRemaining(buffer, 0, 0);
         final byte[] expectedContent = new byte[capacity];
         Arrays.fill(expectedContent, one);
         Assert.assertArrayEquals(expectedContent, originalContent);
         throw expectedEx;
      }
   }

   @Test
   public void testIntToBytes() {
      internalIntToBytesTest(RandomUtil.randomInt(), null);
      internalIntToBytesTest(0, new byte[]{0, 0, 0, 0});
      internalIntToBytesTest(-1, new byte[] {(byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF});
      internalIntToBytesTest(Integer.MIN_VALUE, new byte[] {(byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00});
      internalIntToBytesTest(Integer.MAX_VALUE, new byte[] {(byte)0x7F, (byte)0xFF, (byte)0xFF, (byte)0xFF});
   }

   private void internalIntToBytesTest(int intValue, byte[] manualExpect) {
      byte[] expected = ByteBuffer.allocate(4).putInt(intValue).array();
      byte[] actual = ByteUtil.intToBytes(intValue);
      if (manualExpect != null) {
         Assert.assertEquals(4, manualExpect.length);
         assertArrayEquals(manualExpect, actual);
      }
      assertArrayEquals(expected, actual);

      assertEquals(intValue, ByteUtil.bytesToInt(expected));
      assertEquals(intValue, ByteUtil.bytesToInt(actual));
   }

   @Test
   public void testLongToBytes() {
      internalLongToBytesTest(RandomUtil.randomLong(), null);
      internalLongToBytesTest(0, new byte[] {0, 0, 0, 0, 0, 0, 0, 0});
      internalLongToBytesTest(-1, new byte[] {(byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF});
      internalLongToBytesTest(Long.MIN_VALUE, new byte[] {(byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00});
      internalLongToBytesTest(Long.MAX_VALUE, new byte[] {(byte)0x7F, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF});
   }

   private void internalLongToBytesTest(long longValue, byte[] manualExpected) {
      byte[] expected = ByteBuffer.allocate(8).putLong(longValue).array();
      byte[] actual = ByteUtil.longToBytes(longValue);
      if (manualExpected != null) {
         Assert.assertEquals(8, manualExpected.length);
         assertArrayEquals(manualExpected, actual);
      }
      assertArrayEquals(expected, actual);

      assertEquals(longValue, ByteUtil.bytesToLong(expected));
      assertEquals(longValue, ByteUtil.bytesToLong(actual));
   }

   @Test
   public void testDoubleLongToBytes() {
      long randomLong1 = RandomUtil.randomLong();
      long randomLong2 = RandomUtil.randomLong();
      ByteBuffer buffer = ByteBuffer.allocate(16);
      buffer.putLong(randomLong1);
      buffer.putLong(randomLong2);
      byte[] assertContent = buffer.array();

      byte[] convertedContent = ByteUtil.doubleLongToBytes(randomLong1, randomLong2);

      assertArrayEquals(assertContent, convertedContent);
   }


}
