// 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.

#include "kudu/common/types.h"

#include <cmath>
#include <cstdint>
#include <limits>
#include <string>
#include <tuple>  // IWYU pragma: keep
#include <utility>
#include <vector>

#include <gflags/gflags.h>
#include <gtest/gtest.h>

#include "kudu/common/common.pb.h"
#include "kudu/gutil/mathlimits.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/util/slice.h"
#include "kudu/util/test_util.h"

using std::get;
using std::make_tuple;
using std::nextafter;
using std::string;
using std::tuple;
using std::vector;

namespace kudu {

class TestTypes : public KuduTest {
 protected:
  static void TestDateToString(const string& expected, int32_t date) {
    const TypeInfo* info = GetTypeInfo(DATE);
    string result;
    info->AppendDebugStringForValue(&date, &result);
    ASSERT_EQ(expected, result);
  }
};

TEST_F(TestTypes, TestDatePrinting) {
#if defined(__APPLE__)
  // On MacOS the `%F` date format pads the year with zeros.
  TestDateToString("0001-01-01", *DataTypeTraits<DATE>::min_value());
#else
  TestDateToString("1-01-01", *DataTypeTraits<DATE>::min_value());
#endif
  TestDateToString("9999-12-31", *DataTypeTraits<DATE>::max_value());
  TestDateToString("1970-01-01", 0);
  TestDateToString("1942-08-16", -10000);
  TestDateToString("1997-05-19", 10000);
  TestDateToString("value -2147483648 out of range for DATE type",
                   std::numeric_limits<int32_t>::min());
  TestDateToString("value 2147483647 out of range for DATE type",
                   std::numeric_limits<int32_t>::max());
  TestDateToString("value -719163 out of range for DATE type",
                   *DataTypeTraits<DATE>::min_value() - 1);
  TestDateToString("value 2932897 out of range for DATE type",
                   *DataTypeTraits<DATE>::max_value() + 1);
}

TEST_F(TestTypes, TestTimestampPrinting) {
  const TypeInfo* info = GetTypeInfo(UNIXTIME_MICROS);

  // Test the minimum value
  int64_t time;
  info->CopyMinValue(&time);
  string result;
  info->AppendDebugStringForValue(&time, &result);
  ASSERT_EQ("-290308-12-21T19:59:05.224192Z", result);
  result = "";

  // Test a regular negative timestamp.
  time = -1454368523123456;
  info->AppendDebugStringForValue(&time, &result);
  ASSERT_EQ("1923-12-01T00:44:36.876544Z", result);
  result = "";

  // Test that passing 0 microseconds returns the correct time (0 msecs after the epoch).
  // This is a test for a bug where printing a timestamp with the value 0 would return the
  // current time instead.
  time = 0;
  info->AppendDebugStringForValue(&time, &result);
  ASSERT_EQ("1970-01-01T00:00:00.000000Z", result);
  result = "";

  // Test a regular positive timestamp.
  time = 1454368523123456;
  info->AppendDebugStringForValue(&time, &result);
  ASSERT_EQ("2016-02-01T23:15:23.123456Z", result);
  result = "";

  // Test the maximum value.
  time = MathLimits<int64_t>::kMax;
  info->AppendDebugStringForValue(&time, &result);
  ASSERT_EQ("294247-01-10T04:00:54.775807Z", result);
  result = "";

  {
    // Check that row values are redacted when --redact is set with 'log'.
    google::FlagSaver flag_saver;
    ASSERT_NE("", gflags::SetCommandLineOption("redact", "log"));
    time = 0;
    info->AppendDebugStringForValue(&time, &result);
    ASSERT_EQ("<redacted>", result);
    result = "";
  }
}

namespace {
  template <typename T>
  void TestAreConsecutive(DataType type, vector<tuple<T, T, bool>> test_cases) {
    const TypeInfo* info = GetTypeInfo(type);
    for (auto test_case : test_cases) {
      string lower, upper;
      info->AppendDebugStringForValue(&get<0>(test_case), &lower);
      info->AppendDebugStringForValue(&get<1>(test_case), &upper);
      SCOPED_TRACE(strings::Substitute("lower: $0, upper: $1, expected: $2",
                                       lower, upper, get<2>(test_case)));

      ASSERT_EQ(get<2>(test_case), info->AreConsecutive(&get<0>(test_case), &get<1>(test_case)));
    }
  }
} // anonymous namespace

TEST_F(TestTypes, TestAreConsecutiveInteger) {
  vector<tuple<int64_t, int64_t, bool>> test_cases {
    make_tuple(0, 0, false),
    make_tuple(0, 1, true),
    make_tuple(-1, 0, true),
    make_tuple(INT64_MAX, 0, false),
    make_tuple(0, INT64_MAX, false),
    make_tuple(INT64_MAX - 1, INT64_MAX, true),
    make_tuple(INT64_MIN, 0, false),
    make_tuple(INT64_MIN, INT64_MIN + 1, true),
    make_tuple(INT64_MIN, 0, false),
    make_tuple(-32, -31, true),
    make_tuple(42, 43, true),
    make_tuple(99, -98, false),
  };
  TestAreConsecutive(INT64, test_cases);
}

TEST_F(TestTypes, TestAreConsecutiveDouble) {
  vector<tuple<double, double, bool>> test_cases {
    make_tuple(0.0, 1.0, false),
    make_tuple(0.0, 0.1, false),
    make_tuple(0, nextafter(0, INFINITY), true),
    make_tuple(123.45, nextafter(123.45, INFINITY), true),
    make_tuple(-123.45, nextafter(-123.45, INFINITY), true),
    make_tuple(123.45, 88.0, false),
  };
  TestAreConsecutive(DOUBLE, test_cases);
}

TEST_F(TestTypes, TestAreConsecutiveString) {
  vector<tuple<Slice, Slice, bool>> test_cases {
    make_tuple("abc", "abc", false),
    make_tuple("abc", Slice("abc\0", 4), true),
    make_tuple("", Slice("\0", 1), true),
    make_tuple("", Slice("\1", 1), false),
    make_tuple("", "", false),
    make_tuple("", "a", false),
    make_tuple("abacadaba", Slice("abacadaba\0", 10), true),
  };
  TestAreConsecutive(STRING, test_cases);
}

} // namespace kudu
