/*
 * 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.druid.query.cache;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.apache.druid.java.util.common.Cacheable;
import org.apache.druid.java.util.common.StringUtils;
import org.junit.Assert;
import org.junit.Test;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class CacheKeyBuilderTest
{
  @Test
  public void testCacheKeyBuilder()
  {
    final Cacheable cacheable = () -> new byte[]{10, 20};

    final byte[] actual = new CacheKeyBuilder((byte) 10)
        .appendBoolean(false)
        .appendString("test")
        .appendInt(10)
        .appendLong(Long.MAX_VALUE)
        .appendFloat(0.1f)
        .appendDouble(2.3)
        .appendByteArray(CacheKeyBuilder.STRING_SEPARATOR) // test when an item is same with the separator
        .appendFloatArray(new float[]{10.0f, 11.0f})
        .appendStrings(Lists.newArrayList("test1", "test2"))
        .appendCacheable(cacheable)
        .appendCacheable(null)
        .appendCacheables(Lists.newArrayList(cacheable, null, cacheable))
        .build();

    final int expectedSize = 1                                           // id
                             + 1                                         // bool
                             + 4                                         // 'test'
                             + Integer.BYTES                             // 10
                             + Long.BYTES                                // Long.MAX_VALUE
                             + Float.BYTES                               // 0.1f
                             + Double.BYTES                              // 2.3
                             + CacheKeyBuilder.STRING_SEPARATOR.length   // byte array
                             + Float.BYTES * 2                           // 10.0f, 11.0f
                             + Integer.BYTES + 5 * 2 + 1                 // 'test1' 'test2'
                             + cacheable.getCacheKey().length            // cacheable
                             + Integer.BYTES + 4                         // cacheable list
                             + 12;                                       // type keys
    Assert.assertEquals(expectedSize, actual.length);

    final byte[] expected = ByteBuffer.allocate(expectedSize)
                                      .put((byte) 10)
                                      .put(CacheKeyBuilder.BOOLEAN_KEY)
                                      .put((byte) 0)
                                      .put(CacheKeyBuilder.STRING_KEY)
                                      .put(StringUtils.toUtf8("test"))
                                      .put(CacheKeyBuilder.INT_KEY)
                                      .putInt(10)
                                      .put(CacheKeyBuilder.LONG_KEY)
                                      .putLong(Long.MAX_VALUE)
                                      .put(CacheKeyBuilder.FLOAT_KEY)
                                      .putFloat(0.1f)
                                      .put(CacheKeyBuilder.DOUBLE_KEY)
                                      .putDouble(2.3)
                                      .put(CacheKeyBuilder.BYTE_ARRAY_KEY)
                                      .put(CacheKeyBuilder.STRING_SEPARATOR)
                                      .put(CacheKeyBuilder.FLOAT_ARRAY_KEY)
                                      .putFloat(10.0f)
                                      .putFloat(11.0f)
                                      .put(CacheKeyBuilder.STRING_LIST_KEY)
                                      .putInt(2)
                                      .put(StringUtils.toUtf8("test1"))
                                      .put(CacheKeyBuilder.STRING_SEPARATOR)
                                      .put(StringUtils.toUtf8("test2"))
                                      .put(CacheKeyBuilder.CACHEABLE_KEY)
                                      .put(cacheable.getCacheKey())
                                      .put(CacheKeyBuilder.CACHEABLE_KEY)
                                      .put(CacheKeyBuilder.CACHEABLE_LIST_KEY)
                                      .putInt(3)
                                      .put(cacheable.getCacheKey())
                                      .put(cacheable.getCacheKey())
                                      .array();

    Assert.assertArrayEquals(expected, actual);
  }

  @Test
  public void testDifferentOrderList()
  {
    byte[] key1 = new CacheKeyBuilder((byte) 10)
        .appendStringsIgnoringOrder(Lists.newArrayList("AB", "BA"))
        .build();

    byte[] key2 = new CacheKeyBuilder((byte) 10)
        .appendStringsIgnoringOrder(Lists.newArrayList("BA", "AB"))
        .build();

    Assert.assertArrayEquals(key1, key2);

    final Cacheable cacheable1 = () -> new byte[]{1};

    final Cacheable cacheable2 = () -> new byte[]{2};

    key1 = new CacheKeyBuilder((byte) 10)
        .appendCacheablesIgnoringOrder(Lists.newArrayList(cacheable1, cacheable2))
        .build();

    key2 = new CacheKeyBuilder((byte) 10)
        .appendCacheablesIgnoringOrder(Lists.newArrayList(cacheable2, cacheable1))
        .build();

    Assert.assertArrayEquals(key1, key2);
  }

  @Test
  public void testNotEqualStrings()
  {
    final List<byte[]> keys = new ArrayList<>();
    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendString("test")
            .appendString("test")
            .build()
    );

    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendString("testtest")
            .build()
    );

    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendString("testtest")
            .appendString("")
            .build()
    );

    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendString("")
            .appendString("testtest")
            .build()
    );

    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendStrings(ImmutableList.of("test", "test"))
            .build()
    );

    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendStrings(ImmutableList.of("testtest"))
            .build()
    );

    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendStrings(ImmutableList.of("testtest", ""))
            .build()
    );

    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendStrings(ImmutableList.of("testtest"))
            .appendStrings(ImmutableList.of())
            .build()
    );

    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendStrings(ImmutableList.of())
            .appendStrings(ImmutableList.of("testtest"))
            .build()
    );

    assertNotEqualsEachOther(keys);
  }

  @Test
  public void testNotEqualCacheables()
  {
    final Cacheable test = () -> StringUtils.toUtf8("test");

    final Cacheable testtest = () -> StringUtils.toUtf8("testtest");

    final List<byte[]> keys = new ArrayList<>();
    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendCacheable(test)
            .appendCacheable(test)
            .build()
    );

    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendCacheable(testtest)
            .build()
    );

    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendCacheables(Lists.newArrayList(test, test))
            .build()
    );

    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendCacheables(Collections.singletonList(testtest))
            .build()
    );

    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendCacheables(Collections.singletonList(testtest))
            .appendCacheables(new ArrayList<>())
            .build()
    );

    keys.add(
        new CacheKeyBuilder((byte) 10)
            .appendCacheables(new ArrayList<>())
            .appendCacheables(Collections.singletonList(testtest))
            .build()
    );

    assertNotEqualsEachOther(keys);
  }

  private static void assertNotEqualsEachOther(List<byte[]> keys)
  {
    for (int i = 0; i < keys.size(); i++) {
      for (int j = i + 1; j < keys.size(); j++) {
        Assert.assertFalse(Arrays.equals(keys.get(i), keys.get(j)));
      }
    }
  }

  @Test
  public void testEmptyOrNullStringLists()
  {
    byte[] key1 = new CacheKeyBuilder((byte) 10)
        .appendStrings(Lists.newArrayList("", ""))
        .build();

    byte[] key2 = new CacheKeyBuilder((byte) 10)
        .appendStrings(Collections.singletonList(""))
        .build();

    Assert.assertFalse(Arrays.equals(key1, key2));

    key1 = new CacheKeyBuilder((byte) 10)
        .appendStrings(Collections.singletonList(""))
        .build();

    key2 = new CacheKeyBuilder((byte) 10)
        .appendStrings(Collections.singletonList(null))
        .build();

    Assert.assertArrayEquals(key1, key2);
  }

  @Test
  public void testEmptyOrNullCacheables()
  {
    final byte[] key1 = new CacheKeyBuilder((byte) 10)
        .appendCacheables(new ArrayList<>())
        .build();

    final byte[] key2 = new CacheKeyBuilder((byte) 10)
        .appendCacheables(Collections.singletonList(null))
        .build();

    Assert.assertFalse(Arrays.equals(key1, key2));
  }

  @Test
  public void testIgnoringOrder()
  {
    byte[] actual = new CacheKeyBuilder((byte) 10)
        .appendStringsIgnoringOrder(Lists.newArrayList("test2", "test1", "te"))
        .build();

    byte[] expected = ByteBuffer.allocate(20)
                                .put((byte) 10)
                                .put(CacheKeyBuilder.STRING_LIST_KEY)
                                .putInt(3)
                                .put(StringUtils.toUtf8("te"))
                                .put(CacheKeyBuilder.STRING_SEPARATOR)
                                .put(StringUtils.toUtf8("test1"))
                                .put(CacheKeyBuilder.STRING_SEPARATOR)
                                .put(StringUtils.toUtf8("test2"))
                                .array();

    Assert.assertArrayEquals(expected, actual);

    final Cacheable c1 = () -> StringUtils.toUtf8("te");

    final Cacheable c2 = () -> StringUtils.toUtf8("test1");

    final Cacheable c3 = () -> StringUtils.toUtf8("test2");

    actual = new CacheKeyBuilder((byte) 10)
        .appendCacheablesIgnoringOrder(Lists.newArrayList(c3, c2, c1))
        .build();

    expected = ByteBuffer.allocate(18)
                         .put((byte) 10)
                         .put(CacheKeyBuilder.CACHEABLE_LIST_KEY)
                         .putInt(3)
                         .put(c1.getCacheKey())
                         .put(c2.getCacheKey())
                         .put(c3.getCacheKey())
                         .array();

    Assert.assertArrayEquals(expected, actual);
  }
}
