// Copyright 2025 The Abseil Authors.
//
// Licensed 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
//
//      https://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 "absl/log/internal/container.h"

#include <cstdint>
#include <memory>
#include <ostream>
#include <set>
#include <sstream>
#include <string>
#include <vector>

#include "gtest/gtest.h"
#include "absl/base/config.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "absl/types/span.h"

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace log_internal {
namespace {

class ContainerLoggingTest : public ::testing::Test {
 protected:
  ContainerLoggingTest() : stream_(new std::stringstream) {}
  std::ostream& stream() { return *stream_; }
  std::string logged() {
    std::string r = stream_->str();
    stream_ = std::make_unique<std::stringstream>();
    return r;
  }

 private:
  std::unique_ptr<std::stringstream> stream_;
};

TEST_F(ContainerLoggingTest, ShortRange) {
  std::vector<std::string> words = {"hi", "hello"};
  LogRangeToStream(stream(), words.begin(), words.end(), LogMultiline());
  EXPECT_EQ("[\nhi\nhello\n]", logged());
}

TEST_F(ContainerLoggingTest, LegacyRange) {
  std::vector<int> lengths = {1, 2};
  LogRangeToStream(stream(), lengths.begin(), lengths.end(),
                   LogLegacyUpTo100());
  EXPECT_EQ("1 2", logged());
}

TEST_F(ContainerLoggingTest, ToString) {
  std::vector<int> lengths = {1, 2, 3, 4, 5};
  EXPECT_EQ(LogContainer(lengths).str(), "[1, 2, 3, 4, 5]");
}

class UserDefFriend {
 public:
  explicit UserDefFriend(int i) : i_(i) {}

 private:
  friend std::ostream& operator<<(std::ostream& str, const UserDefFriend& i) {
    return str << i.i_;
  }
  int i_;
};

TEST_F(ContainerLoggingTest, RangeOfUserDefined) {
  std::vector<UserDefFriend> ints = {UserDefFriend(1), UserDefFriend(2),
                                     UserDefFriend(3)};
  LogRangeToStream(stream(), ints.begin(), ints.begin() + 1, LogDefault());
  LogRangeToStream(stream(), ints.begin() + 1, ints.begin() + 2,
                   LogMultiline());
  LogRangeToStream(stream(), ints.begin() + 2, ints.begin() + 3, LogDefault());
  LogRangeToStream(stream(), ints.begin(), ints.begin(), LogMultiline());

  EXPECT_EQ("[1][\n2\n][3][\n]", logged());
}

TEST_F(ContainerLoggingTest, FullContainer) {
  std::vector<int> ints;
  std::vector<int> ints100;
  std::vector<int> ints123;
  int64_t max_elements = 123;
  std::string expected1;
  std::string expected2;
  std::string expected3;
  std::string expected4;
  std::string expected5;
  std::string expected6;
  std::string expected7;
  std::string expected8;
  std::string expected9;
  for (int i = 0; i < 1000; ++i) {
    ints.push_back(i);
    if (i < 100) {
      ints100.push_back(i);
    }
    if (i < max_elements) {
      ints123.push_back(i);
    }
  }
  expected1 = "[\n" + absl::StrJoin(ints, "\n") + "\n]";
  expected2 = "[" + absl::StrJoin(ints, ", ") + "]";
  expected3 = "[\n" + absl::StrJoin(ints100, "\n") + "\n...\n]";
  expected4 = "[" + absl::StrJoin(ints100, ", ") + ", ...]";
  expected5 = absl::StrJoin(ints100, " ") + " ...";
  expected6 = "[\n" + absl::StrJoin(ints, "\n") + "\n]";
  expected7 = "[\n" + absl::StrJoin(ints123, "\n") + "\n...\n]";
  expected8 = "[" + absl::StrJoin(ints, ", ") + "]";
  expected9 = "[" + absl::StrJoin(ints123, ", ") + ", ...]";

  LogRangeToStream(stream(), ints.begin(), ints.end(), LogMultiline());
  EXPECT_EQ(expected1, logged());
  LogRangeToStream(stream(), ints.begin(), ints.end(), LogShort());
  EXPECT_EQ(expected2, logged());
  LogRangeToStream(stream(), ints.begin(), ints.end(), LogMultilineUpTo100());
  EXPECT_EQ(expected3, logged());
  LogRangeToStream(stream(), ints.begin(), ints.end(), LogShortUpTo100());
  EXPECT_EQ(expected4, logged());
  LogRangeToStream(stream(), ints.begin(), ints.end(), LogLegacyUpTo100());
  EXPECT_EQ(expected5, logged());

  LogRangeToStream(stream(), ints.begin(), ints.end(),
                   LogMultilineUpToN(ints.size()));
  EXPECT_EQ(expected6, logged());
  LogRangeToStream(stream(), ints.begin(), ints.end(),
                   LogMultilineUpToN(max_elements));
  EXPECT_EQ(expected7, logged());
  LogRangeToStream(stream(), ints.begin(), ints.end(),
                   LogShortUpToN(ints.size()));
  EXPECT_EQ(expected8, logged());
  LogRangeToStream(stream(), ints.begin(), ints.end(),
                   LogShortUpToN(max_elements));
  EXPECT_EQ(expected9, logged());
}

TEST_F(ContainerLoggingTest, LogContainer) {
  std::set<int> ints = {1, 2, 3};
  stream() << LogContainer(ints, LogMultiline());
  EXPECT_EQ("[\n1\n2\n3\n]", logged());

  stream() << LogContainer(ints);
  EXPECT_EQ("[1, 2, 3]", logged());

  stream() << LogContainer(std::vector<int>(ints.begin(), ints.end()),
                           LogLegacyUpTo100());
  EXPECT_EQ("1 2 3", logged());
}

TEST_F(ContainerLoggingTest, LogMutableSpan) {
  std::vector<int> ints = {1, 2, 3};
  absl::Span<int> int_span(ints);
  stream() << LogContainer(int_span);
  EXPECT_EQ("[1, 2, 3]", logged());
}

TEST_F(ContainerLoggingTest, LogRange) {
  std::set<int> ints = {1, 2, 3};
  stream() << LogRange(ints.begin(), ints.end(), LogMultiline());
  EXPECT_EQ("[\n1\n2\n3\n]", logged());

  stream() << LogRange(ints.begin(), ints.end());
  EXPECT_EQ("[1, 2, 3]", logged());
}

// Some class with a custom Stringify
class C {
 public:
  explicit C(int x) : x_(x) {}

 private:
  // This is intentionally made private for the purposes of the test;
  //` AbslStringify` isn't meant to be called directly, and instead invoked
  // via `StrCat` and friends.
  template <typename Sink>
  friend void AbslStringify(Sink& sink, const C& p) {
    absl::Format(&sink, "C(%d)", p.x_);
  }

  int x_;
};

TEST_F(ContainerLoggingTest, LogContainerWithCustomStringify) {
  std::vector<C> c = {C(1), C(2), C(3)};
  stream() << LogContainer(c);
  EXPECT_EQ("[C(1), C(2), C(3)]", logged());
}

class LogEnumTest : public ContainerLoggingTest {
 protected:
  enum Unscoped { kUnscoped0, kUnscoped1, kUnscoped2 };

  enum StreamableUnscoped {
    kStreamableUnscoped0,
    kStreamableUnscoped1,
    kStreamableUnscoped2
  };

  enum class Scoped { k0, k1, k2 };

  enum class StreamableScoped { k0, k1, k2 };

  friend std::ostream& operator<<(std::ostream& os, StreamableUnscoped v) {
    return os << LogEnum(v);
  }

  friend std::ostream& operator<<(std::ostream& os, StreamableScoped v) {
    return os << LogEnum(v);
  }
};

TEST_F(LogEnumTest, Unscoped) {
  stream() << LogEnum(kUnscoped0) << "," << LogEnum(kUnscoped1) << ","
           << LogEnum(kUnscoped2);
  EXPECT_EQ("0,1,2", logged());
}

TEST_F(LogEnumTest, StreamableUnscoped) {
  stream() << kStreamableUnscoped0 << "," << kStreamableUnscoped1 << ","
           << kStreamableUnscoped2;
  EXPECT_EQ("0,1,2", logged());
}

TEST_F(LogEnumTest, Scoped) {
  stream() << LogEnum(Scoped::k0) << "," << LogEnum(Scoped::k1) << ","
           << LogEnum(Scoped::k2);
  EXPECT_EQ("0,1,2", logged());
}

TEST_F(LogEnumTest, StreamableScoped) {
  // Test using LogEnum to implement an operator<<.
  stream() << StreamableScoped::k0 << "," << StreamableScoped::k1 << ","
           << StreamableScoped::k2;
  EXPECT_EQ("0,1,2", logged());
}

}  // namespace
}  // namespace log_internal
ABSL_NAMESPACE_END
}  // namespace absl
