// Copyright 2020 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 <cstdlib>
#include <ctime>
#include <memory>
#include <random>
#include <sstream>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/debugging/leak_check.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_ring.h"
#include "absl/strings/internal/cord_rep_ring_reader.h"
#include "absl/strings/string_view.h"

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
namespace {

using testing::Eq;

// Creates a flat for testing
CordRep* MakeFlat(absl::string_view s) {
  CordRepFlat* flat = CordRepFlat::New(s.length());
  memcpy(flat->Data(), s.data(), s.length());
  flat->length = s.length();
  return flat;
}

CordRepRing* FromFlats(Span<absl::string_view const> flats) {
  CordRepRing* ring = CordRepRing::Create(MakeFlat(flats[0]), flats.size() - 1);
  for (int i = 1; i < flats.size(); ++i) {
    ring = CordRepRing::Append(ring, MakeFlat(flats[i]));
  }
  return ring;
}

std::array<absl::string_view, 12> TestFlats() {
  return {"abcdefghij", "klmnopqrst", "uvwxyz",     "ABCDEFGHIJ",
          "KLMNOPQRST", "UVWXYZ",     "1234567890", "~!@#$%^&*()_",
          "+-=",        "[]\\{}|;':", ",/<>?",      "."};
}

TEST(CordRingReaderTest, DefaultInstance) {
  CordRepRingReader reader;
  EXPECT_FALSE(static_cast<bool>(reader));
  EXPECT_THAT(reader.ring(), Eq(nullptr));
#ifndef NDEBUG
  EXPECT_DEATH_IF_SUPPORTED(reader.length(), ".*");
  EXPECT_DEATH_IF_SUPPORTED(reader.consumed(), ".*");
  EXPECT_DEATH_IF_SUPPORTED(reader.remaining(), ".*");
  EXPECT_DEATH_IF_SUPPORTED(reader.Next(), ".*");
  EXPECT_DEATH_IF_SUPPORTED(reader.Seek(0), ".*");
#endif
}

TEST(CordRingReaderTest, Reset) {
  CordRepRingReader reader;
  auto flats = TestFlats();
  CordRepRing* ring = FromFlats(flats);

  absl::string_view first = reader.Reset(ring);
  EXPECT_THAT(first, Eq(flats[0]));
  EXPECT_TRUE(static_cast<bool>(reader));
  EXPECT_THAT(reader.ring(), Eq(ring));
  EXPECT_THAT(reader.index(), Eq(ring->head()));
  EXPECT_THAT(reader.length(), Eq(ring->length));
  EXPECT_THAT(reader.consumed(), Eq(flats[0].length()));
  EXPECT_THAT(reader.remaining(), Eq(ring->length - reader.consumed()));

  reader.Reset();
  EXPECT_FALSE(static_cast<bool>(reader));
  EXPECT_THAT(reader.ring(), Eq(nullptr));

  CordRep::Unref(ring);
}

TEST(CordRingReaderTest, Next) {
  CordRepRingReader reader;
  auto flats = TestFlats();
  CordRepRing* ring = FromFlats(flats);
  CordRepRing::index_type head = ring->head();

  reader.Reset(ring);
  size_t consumed = reader.consumed();
  size_t remaining = reader.remaining();
  for (int i = 1; i < flats.size(); ++i) {
    consumed += flats[i].length();
    remaining -= flats[i].length();
    absl::string_view next = reader.Next();
    ASSERT_THAT(next, Eq(flats[i]));
    ASSERT_THAT(reader.index(), Eq(ring->advance(head, i)));
    ASSERT_THAT(reader.consumed(), Eq(consumed));
    ASSERT_THAT(reader.remaining(), Eq(remaining));
  }

#ifndef NDEBUG
  EXPECT_DEATH_IF_SUPPORTED(reader.Next(), ".*");
#endif

  CordRep::Unref(ring);
}

TEST(CordRingReaderTest, SeekForward) {
  CordRepRingReader reader;
  auto flats = TestFlats();
  CordRepRing* ring = FromFlats(flats);
  CordRepRing::index_type head = ring->head();

  reader.Reset(ring);
  size_t consumed = 0;
  size_t remaining = ring->length;;
  for (int i = 0; i < flats.size(); ++i) {
    size_t offset = consumed;
    consumed += flats[i].length();
    remaining -= flats[i].length();
    for (int off = 0; off < flats[i].length(); ++off) {
      absl::string_view chunk = reader.Seek(offset + off);
      ASSERT_THAT(chunk, Eq(flats[i].substr(off)));
      ASSERT_THAT(reader.index(), Eq(ring->advance(head, i)));
      ASSERT_THAT(reader.consumed(), Eq(consumed));
      ASSERT_THAT(reader.remaining(), Eq(remaining));
    }
  }

  CordRep::Unref(ring);
}

TEST(CordRingReaderTest, SeekBackward) {
  CordRepRingReader reader;
  auto flats = TestFlats();
  CordRepRing* ring = FromFlats(flats);
  CordRepRing::index_type head = ring->head();

  reader.Reset(ring);
  size_t consumed = ring->length;
  size_t remaining = 0;
  for (int i = flats.size() - 1; i >= 0; --i) {
    size_t offset = consumed - flats[i].length();
    for (int off = 0; off < flats[i].length(); ++off) {
      absl::string_view chunk = reader.Seek(offset + off);
      ASSERT_THAT(chunk, Eq(flats[i].substr(off)));
      ASSERT_THAT(reader.index(), Eq(ring->advance(head, i)));
      ASSERT_THAT(reader.consumed(), Eq(consumed));
      ASSERT_THAT(reader.remaining(), Eq(remaining));
    }
    consumed -= flats[i].length();
    remaining += flats[i].length();
  }
#ifndef NDEBUG
  EXPECT_DEATH_IF_SUPPORTED(reader.Seek(ring->length), ".*");
#endif
  CordRep::Unref(ring);
}

}  // namespace
}  // namespace cord_internal
ABSL_NAMESPACE_END
}  // namespace absl
