/**
 *
 * 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 <functional>
#include <string>
#include <type_traits>

#include "../TestBase.h"
#include "utils/GeneralUtils.h"

namespace utils = org::apache::nifi::minifi::utils;

static_assert(std::is_same<decltype(utils::make_unique<char16_t>()), std::unique_ptr<char16_t>>::value, "utils::make_unique type must be correct");

TEST_CASE("GeneralUtils::make_unique", "[make_unique]") {
  const auto pstr = utils::make_unique<std::string>("test string");
  REQUIRE("test string" == *pstr);
}

// intdiv_ceil
static_assert(0 == utils::intdiv_ceil(0, 1), "");
static_assert(0 == utils::intdiv_ceil(0, 2), "");
static_assert(1 == utils::intdiv_ceil(1, 2), "");
static_assert(1 == utils::intdiv_ceil(1, 3), "");
static_assert(1 == utils::intdiv_ceil(3, 3), "");
static_assert(2 == utils::intdiv_ceil(4, 3), "");
static_assert(2 == utils::intdiv_ceil(5, 3), "");
static_assert(0 == utils::intdiv_ceil(-1, 3), "");
static_assert(-1 == utils::intdiv_ceil(-3, 3), "");
static_assert(-1 == utils::intdiv_ceil(-4, 3), "");
static_assert(2 == utils::intdiv_ceil(-4, -3), "");
static_assert(2 == utils::intdiv_ceil(-5, -3), "");
static_assert(0 == utils::intdiv_ceil(1, -3), "");
static_assert(-1 == utils::intdiv_ceil(5, -3), "");
static_assert(3 == utils::intdiv_ceil(6, 2), "");
static_assert(-3 == utils::intdiv_ceil(-6, 2), "");
static_assert(-3 == utils::intdiv_ceil(6, -2), "");
static_assert(3 == utils::intdiv_ceil(-6, -2), "");
static_assert(0 == utils::intdiv_ceil(0, -10), "");

template<int N, int D, typename = void>
struct does_compile : std::false_type {};

template<int N, int D>
struct does_compile<N, D,
    // we must force evaluation so decltype won't do
    typename std::enable_if<(utils::intdiv_ceil(N, D), true)>::type> : std::true_type {};

static_assert(does_compile<2, 3>::value, "does_compile should work");
static_assert(!does_compile<1, 0>::value, "constexpr division by zero shouldn't compile");


TEST_CASE("GeneralUtils::exchange", "[exchange]") {
  int a = 1;
  int b = 2;
  a = utils::exchange(b, 0);
  REQUIRE(2 == a);
  REQUIRE(0 == b);
}

static_assert(std::is_same<decltype(utils::void_t<char16_t>()), void>::value, "utils::void_t single arg must work");
static_assert(std::is_same<decltype(utils::void_t<int, double, bool, void, char16_t>()), void>::value, "utils::void_t multi arg must work");

TEST_CASE("GeneralUtils::invoke pointer to member function", "[invoke memfnptr]") {
  const int result{0xc1ca};
  struct Tester {
    bool called{};
    int memfn(const int arg) {
      REQUIRE(42 == arg);
      called = true;
      return result;
    }
  };

  // normal
  REQUIRE(result == utils::invoke(&Tester::memfn, Tester{}, 42));

  // reference_wrapper
  Tester t2;
  const auto ref_wrapper = std::ref(t2);
  REQUIRE(result == utils::invoke(&Tester::memfn, ref_wrapper, 42));
  REQUIRE(t2.called);

  // pointer
  Tester t3;
  REQUIRE(result == utils::invoke(&Tester::memfn, &t3, 42));
  REQUIRE(t3.called);
}

TEST_CASE("GeneralUtils::invoke pointer to data member", "[invoke data member]") {
  struct Times2 {
    int value;
    explicit Times2(const int i) :value{i * 2} {}
  };

  // normal
  REQUIRE(24 == utils::invoke(&Times2::value, Times2{12}));

  // reference_wrapper
  Times2 t2{42};
  const auto ref_wrapper = std::ref(t2);
  REQUIRE(84 == utils::invoke(&Times2::value, ref_wrapper));

  // pointer
  Times2 t3{0};
  REQUIRE(0 == utils::invoke(&Times2::value, &t3));
}

namespace {
bool free_function(const bool b) { return b; }
}  // namespace

TEST_CASE("GeneralUtils::invoke FunctionObject", "[invoke function object]") {
  REQUIRE(true == utils::invoke(&free_function, true));
  REQUIRE(false == utils::invoke(&free_function, false));

  const auto n = 3;
  const auto int_timesn = [n](const int i) { return n * i; };

  // lambda with capture
  REQUIRE(60 == utils::invoke(int_timesn, 20));
}
