/*
 * 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.math.expr;

import com.google.common.collect.ImmutableList;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.java.util.common.ISE;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.testing.InitializedNullHandlingTest;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

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

public class ExprEvalTest extends InitializedNullHandlingTest
{
  private static int MAX_SIZE_BYTES = 1 << 13;

  @Rule
  public ExpectedException expectedException = ExpectedException.none();

  ByteBuffer buffer = ByteBuffer.allocate(1 << 16);

  @Test
  public void testStringSerde()
  {
    assertExpr(0, "hello");
    assertExpr(1234, "hello");
    assertExpr(0, ExprEval.bestEffortOf(null));
  }

  @Test
  public void testStringSerdeTooBig()
  {
    expectedException.expect(ISE.class);
    expectedException.expectMessage(StringUtils.format(
        "Unable to serialize [%s], size [%s] is larger than max [%s]",
        ExprType.STRING,
        16,
        10
    ));
    assertExpr(0, ExprEval.of("hello world"), 10);
  }


  @Test
  public void testLongSerde()
  {
    assertExpr(0, 1L);
    assertExpr(1234, 1L);
    assertExpr(1234, ExprEval.ofLong(null));
  }

  @Test
  public void testDoubleSerde()
  {
    assertExpr(0, 1.123);
    assertExpr(1234, 1.123);
    assertExpr(1234, ExprEval.ofDouble(null));
  }

  @Test
  public void testStringArraySerde()
  {
    assertExpr(0, new String[]{"hello", "hi", "hey"});
    assertExpr(1024, new String[]{"hello", null, "hi", "hey"});
    assertExpr(2048, new String[]{});
  }

  @Test
  public void testStringArraySerdeToBig()
  {
    expectedException.expect(ISE.class);
    expectedException.expectMessage(StringUtils.format(
        "Unable to serialize [%s], size [%s] is larger than max [%s]",
        ExprType.STRING_ARRAY,
        14,
        10
    ));
    assertExpr(0, ExprEval.ofStringArray(new String[]{"hello", "hi", "hey"}), 10);
  }

  @Test
  public void testStringArrayEvalToBig()
  {
    expectedException.expect(ISE.class);
    // this has a different failure size than string serde because it doesn't check incrementally
    expectedException.expectMessage(StringUtils.format(
        "Unable to serialize [%s], size [%s] is larger than max [%s]",
        ExprType.STRING_ARRAY,
        27,
        10
    ));
    assertEstimatedBytes(ExprEval.ofStringArray(new String[]{"hello", "hi", "hey"}), 10);
  }

  @Test
  public void testLongArraySerde()
  {
    assertExpr(0, new Long[]{1L, 2L, 3L});
    assertExpr(1234, new Long[]{1L, 2L, null, 3L});
    assertExpr(1234, new Long[]{});
  }

  @Test
  public void testLongArraySerdeTooBig()
  {
    expectedException.expect(ISE.class);
    expectedException.expectMessage(StringUtils.format(
        "Unable to serialize [%s], size [%s] is larger than max [%s]",
        ExprType.LONG_ARRAY,
        29,
        10
    ));
    assertExpr(0, ExprEval.ofLongArray(new Long[]{1L, 2L, 3L}), 10);
  }

  @Test
  public void testLongArrayEvalTooBig()
  {
    expectedException.expect(ISE.class);
    expectedException.expectMessage(StringUtils.format(
        "Unable to serialize [%s], size [%s] is larger than max [%s]",
        ExprType.LONG_ARRAY,
        NullHandling.sqlCompatible() ? 32 : 29,
        10
    ));
    assertEstimatedBytes(ExprEval.ofLongArray(new Long[]{1L, 2L, 3L}), 10);
  }

  @Test
  public void testDoubleArraySerde()
  {
    assertExpr(0, new Double[]{1.1, 2.2, 3.3});
    assertExpr(1234, new Double[]{1.1, 2.2, null, 3.3});
    assertExpr(1234, new Double[]{});
  }

  @Test
  public void testDoubleArraySerdeTooBig()
  {
    expectedException.expect(ISE.class);
    expectedException.expectMessage(StringUtils.format(
        "Unable to serialize [%s], size [%s] is larger than max [%s]",
        ExprType.DOUBLE_ARRAY,
        29,
        10
    ));
    assertExpr(0, ExprEval.ofDoubleArray(new Double[]{1.1, 2.2, 3.3}), 10);
  }

  @Test
  public void testDoubleArrayEvalTooBig()
  {
    expectedException.expect(ISE.class);
    expectedException.expectMessage(StringUtils.format(
        "Unable to serialize [%s], size [%s] is larger than max [%s]",
        ExprType.DOUBLE_ARRAY,
        NullHandling.sqlCompatible() ? 32 : 29,
        10
    ));
    assertEstimatedBytes(ExprEval.ofDoubleArray(new Double[]{1.1, 2.2, 3.3}), 10);
  }

  @Test
  public void test_coerceListToArray()
  {
    Assert.assertNull(ExprEval.coerceListToArray(null, false));
    Assert.assertArrayEquals(new Object[0], (Object[]) ExprEval.coerceListToArray(ImmutableList.of(), false));
    Assert.assertArrayEquals(new String[]{null}, (String[]) ExprEval.coerceListToArray(null, true));
    Assert.assertArrayEquals(new String[]{null}, (String[]) ExprEval.coerceListToArray(ImmutableList.of(), true));

    List<Long> longList = ImmutableList.of(1L, 2L, 3L);
    Assert.assertArrayEquals(new Long[]{1L, 2L, 3L}, (Long[]) ExprEval.coerceListToArray(longList, false));

    List<Integer> intList = ImmutableList.of(1, 2, 3);
    Assert.assertArrayEquals(new Long[]{1L, 2L, 3L}, (Long[]) ExprEval.coerceListToArray(intList, false));

    List<Float> floatList = ImmutableList.of(1.0f, 2.0f, 3.0f);
    Assert.assertArrayEquals(new Double[]{1.0, 2.0, 3.0}, (Double[]) ExprEval.coerceListToArray(floatList, false));

    List<Double> doubleList = ImmutableList.of(1.0, 2.0, 3.0);
    Assert.assertArrayEquals(new Double[]{1.0, 2.0, 3.0}, (Double[]) ExprEval.coerceListToArray(doubleList, false));

    List<String> stringList = ImmutableList.of("a", "b", "c");
    Assert.assertArrayEquals(new String[]{"a", "b", "c"}, (String[]) ExprEval.coerceListToArray(stringList, false));

    List<String> withNulls = new ArrayList<>();
    withNulls.add("a");
    withNulls.add(null);
    withNulls.add("c");
    Assert.assertArrayEquals(new String[]{"a", null, "c"}, (String[]) ExprEval.coerceListToArray(withNulls, false));

    List<Long> withNumberNulls = new ArrayList<>();
    withNumberNulls.add(1L);
    withNumberNulls.add(null);
    withNumberNulls.add(3L);

    Assert.assertArrayEquals(new Long[]{1L, null, 3L}, (Long[]) ExprEval.coerceListToArray(withNumberNulls, false));

    List<Object> withStringMix = ImmutableList.of(1L, "b", 3L);
    Assert.assertArrayEquals(
        new String[]{"1", "b", "3"},
        (String[]) ExprEval.coerceListToArray(withStringMix, false)
    );

    List<Number> withIntsAndLongs = ImmutableList.of(1, 2L, 3);
    Assert.assertArrayEquals(
        new Long[]{1L, 2L, 3L},
        (Long[]) ExprEval.coerceListToArray(withIntsAndLongs, false)
    );

    List<Number> withFloatsAndLongs = ImmutableList.of(1, 2L, 3.0f);
    Assert.assertArrayEquals(
        new Double[]{1.0, 2.0, 3.0},
        (Double[]) ExprEval.coerceListToArray(withFloatsAndLongs, false)
    );

    List<Number> withDoublesAndLongs = ImmutableList.of(1, 2L, 3.0);
    Assert.assertArrayEquals(
        new Double[]{1.0, 2.0, 3.0},
        (Double[]) ExprEval.coerceListToArray(withDoublesAndLongs, false)
    );

    List<Number> withFloatsAndDoubles = ImmutableList.of(1L, 2.0f, 3.0);
    Assert.assertArrayEquals(
        new Double[]{1.0, 2.0, 3.0},
        (Double[]) ExprEval.coerceListToArray(withFloatsAndDoubles, false)
    );

    List<String> withAllNulls = new ArrayList<>();
    withAllNulls.add(null);
    withAllNulls.add(null);
    withAllNulls.add(null);
    Assert.assertArrayEquals(
        new String[]{null, null, null},
        (String[]) ExprEval.coerceListToArray(withAllNulls, false)
    );
  }

  @Test
  public void testStringArrayToNumberArray()
  {
    ExprEval someStringArray = ExprEval.ofStringArray(new String[]{"1", "2", "foo", null, "3.3"});
    Assert.assertArrayEquals(
        new Long[]{1L, 2L, null, null, 3L},
        someStringArray.asLongArray()
    );
    Assert.assertArrayEquals(
        new Double[]{1.0, 2.0, null, null, 3.3},
        someStringArray.asDoubleArray()
    );
  }

  @Test
  public void testEmptyArrayFromList()
  {
    // empty arrays will materialize from JSON into an empty list, which coerce list to array will make into Object[]
    // make sure we can handle it
    ExprEval someEmptyArray = ExprEval.bestEffortOf(new ArrayList<>());
    Assert.assertTrue(someEmptyArray.isArray());
    Assert.assertEquals(0, someEmptyArray.asArray().length);
  }

  private void assertExpr(int position, Object expected)
  {
    assertExpr(position, ExprEval.bestEffortOf(expected));
  }

  private void assertExpr(int position, ExprEval expected)
  {
    assertExpr(position, expected, MAX_SIZE_BYTES);
  }

  private void assertExpr(int position, ExprEval expected, int maxSizeBytes)
  {
    ExprEval.serialize(buffer, position, expected, maxSizeBytes);
    if (ExprType.isArray(expected.type())) {
      Assert.assertArrayEquals(
          expected.asArray(),
          ExprEval.deserialize(buffer, position + 1, ExprType.fromByte(buffer.get(position))).asArray()
      );
      Assert.assertArrayEquals(
          expected.asArray(),
          ExprEval.deserialize(buffer, position).asArray()
      );
    } else {
      Assert.assertEquals(
          expected.value(),
          ExprEval.deserialize(buffer, position + 1, ExprType.fromByte(buffer.get(position))).value()
      );
      Assert.assertEquals(
          expected.value(),
          ExprEval.deserialize(buffer, position).value()
      );
    }
    assertEstimatedBytes(expected, maxSizeBytes);
  }

  private void assertEstimatedBytes(ExprEval eval, int maxSizeBytes)
  {
    ExprEval.estimateAndCheckMaxBytes(eval, maxSizeBytes);
  }
}
