/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/platform/text/bidi_resolver.h"

#include <fstream>

#include "base/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/text/bidi_test_harness.h"
#include "third_party/blink/renderer/platform/text/text_run_iterator.h"

namespace blink {

TEST(BidiResolver, Basic) {
  bool has_strong_directionality;
  String value("foo");
  TextRun run(value);
  BidiResolver<TextRunIterator, BidiCharacterRun> bidi_resolver;
  bidi_resolver.SetStatus(
      BidiStatus(run.Direction(), run.DirectionalOverride()));
  bidi_resolver.SetPositionIgnoringNestedIsolates(TextRunIterator(&run, 0));
  TextDirection direction = bidi_resolver.DetermineParagraphDirectionality(
      &has_strong_directionality);
  EXPECT_TRUE(has_strong_directionality);
  EXPECT_EQ(TextDirection::kLtr, direction);
}

TextDirection DetermineParagraphDirectionality(
    const TextRun& text_run,
    bool* has_strong_directionality = nullptr) {
  BidiResolver<TextRunIterator, BidiCharacterRun> resolver;
  resolver.SetStatus(BidiStatus(TextDirection::kLtr, false));
  resolver.SetPositionIgnoringNestedIsolates(TextRunIterator(&text_run, 0));
  return resolver.DetermineParagraphDirectionality(has_strong_directionality);
}

struct TestData {
  UChar text[3];
  size_t length;
  TextDirection expected_direction;
  bool expected_strong;
};

void TestDirectionality(const TestData& entry) {
  bool has_strong_directionality;
  String data(entry.text, entry.length);
  TextRun run(data);
  TextDirection direction =
      DetermineParagraphDirectionality(run, &has_strong_directionality);
  EXPECT_EQ(entry.expected_strong, has_strong_directionality);
  EXPECT_EQ(entry.expected_direction, direction);
}

TEST(BidiResolver, ParagraphDirectionSurrogates) {
  const TestData kTestData[] = {
      // Test strong RTL, non-BMP. (U+10858 Imperial
      // Aramaic number one, strong RTL)
      {{0xD802, 0xDC58}, 2, TextDirection::kRtl, true},

      // Test strong LTR, non-BMP. (U+1D15F Musical
      // symbol quarter note, strong LTR)
      {{0xD834, 0xDD5F}, 2, TextDirection::kLtr, true},

      // Test broken surrogate: valid leading, invalid
      // trail. (Lead of U+10858, space)
      {{0xD802, ' '}, 2, TextDirection::kLtr, false},

      // Test broken surrogate: invalid leading. (Trail
      // of U+10858, U+05D0 Hebrew Alef)
      {{0xDC58, 0x05D0}, 2, TextDirection::kRtl, true},

      // Test broken surrogate: valid leading, invalid
      // trail/valid lead, valid trail.
      {{0xD802, 0xD802, 0xDC58}, 3, TextDirection::kRtl, true},

      // Test broken surrogate: valid leading, no trail
      // (string too short). (Lead of U+10858)
      {{0xD802, 0xDC58}, 1, TextDirection::kLtr, false},

      // Test broken surrogate: trail appearing before
      // lead. (U+10858 units reversed)
      {{0xDC58, 0xD802}, 2, TextDirection::kLtr, false}};
  for (size_t i = 0; i < base::size(kTestData); ++i)
    TestDirectionality(kTestData[i]);
}

class BidiTestRunner {
 public:
  BidiTestRunner()
      : tests_run_(0),
        tests_skipped_(0),
        ignored_char_failures_(0),
        level_failures_(0),
        order_failures_(0) {}

  void SkipTestsWith(UChar codepoint) {
    skipped_code_points_.insert(codepoint);
  }

  void RunTest(const std::basic_string<UChar>& input,
               const std::vector<int>& reorder,
               const std::vector<int>& levels,
               bidi_test::ParagraphDirection,
               const std::string& line,
               size_t line_number);

  size_t tests_run_;
  size_t tests_skipped_;
  std::set<UChar> skipped_code_points_;
  size_t ignored_char_failures_;
  size_t level_failures_;
  size_t order_failures_;
};

// Blink's UBA does not filter out control characters, etc. Maybe it should?
// Instead it depends on later layers of Blink to simply ignore them.
// This function helps us emulate that to be compatible with BidiTest.txt
// expectations.
static bool IsNonRenderedCodePoint(UChar c) {
  // The tests also expect us to ignore soft-hyphen.
  if (c == 0xAD)
    return true;
  // Control characters are not rendered:
  return c >= 0x202A && c <= 0x202E;
  // But it seems to expect LRI, etc. to be rendered!?
}

std::string DiffString(const std::vector<int>& actual,
                       const std::vector<int>& expected) {
  std::ostringstream diff;
  diff << "actual: ";
  // This is the magical way to print a vector to a stream, clear, right?
  std::copy(actual.begin(), actual.end(),
            std::ostream_iterator<int>(diff, " "));
  diff << " expected: ";
  std::copy(expected.begin(), expected.end(),
            std::ostream_iterator<int>(diff, " "));
  return diff.str();
}

void BidiTestRunner::RunTest(const std::basic_string<UChar>& input,
                             const std::vector<int>& expected_order,
                             const std::vector<int>& expected_levels,
                             bidi_test::ParagraphDirection paragraph_direction,
                             const std::string& line,
                             size_t line_number) {
  if (!skipped_code_points_.empty()) {
    for (size_t i = 0; i < input.size(); i++) {
      if (skipped_code_points_.count(input[i])) {
        tests_skipped_++;
        return;
      }
    }
  }

  tests_run_++;

  TextRun text_run(input.data(), input.size());
  switch (paragraph_direction) {
    case bidi_test::kDirectionAutoLTR:
      text_run.SetDirection(DetermineParagraphDirectionality(text_run));
      break;
    case bidi_test::kDirectionLTR:
      text_run.SetDirection(TextDirection::kLtr);
      break;
    case bidi_test::kDirectionRTL:
      text_run.SetDirection(TextDirection::kRtl);
      break;
    default:
      break;
  }
  BidiResolver<TextRunIterator, BidiCharacterRun> resolver;
  resolver.SetStatus(
      BidiStatus(text_run.Direction(), text_run.DirectionalOverride()));
  resolver.SetPositionIgnoringNestedIsolates(TextRunIterator(&text_run, 0));

  BidiRunList<BidiCharacterRun>& runs = resolver.Runs();
  resolver.CreateBidiRunsForLine(TextRunIterator(&text_run, text_run.length()));

  std::ostringstream error_context;
  error_context << ", line " << line_number << " \"" << line << "\"";
  error_context << " context: "
                << bidi_test::NameFromParagraphDirection(paragraph_direction);

  std::vector<int> actual_order;
  std::vector<int> actual_levels;
  actual_levels.assign(input.size(), -1);
  BidiCharacterRun* run = runs.FirstRun();
  while (run) {
    // Blink's UBA just makes runs, the actual ordering of the display of
    // characters is handled later in our pipeline, so we fake it here:
    bool reversed = run->Reversed(false);
    DCHECK_GE(run->Stop(), run->Start());
    size_t length = run->Stop() - run->Start();
    for (size_t i = 0; i < length; i++) {
      int input_index = reversed ? run->Stop() - i - 1 : run->Start() + i;
      if (!IsNonRenderedCodePoint(input[input_index]))
        actual_order.push_back(input_index);
      // BidiTest.txt gives expected level data in the order of the original
      // input.
      actual_levels[input_index] = run->Level();
    }
    run = run->Next();
  }

  if (expected_order.size() != actual_order.size()) {
    ignored_char_failures_++;
    EXPECT_EQ(expected_order.size(), actual_order.size())
        << error_context.str();
  } else if (expected_order != actual_order) {
    order_failures_++;
    printf("ORDER %s%s\n", DiffString(actual_order, expected_order).c_str(),
           error_context.str().c_str());
  }

  if (expected_levels.size() != actual_levels.size()) {
    ignored_char_failures_++;
    EXPECT_EQ(expected_levels.size(), actual_levels.size())
        << error_context.str();
  } else {
    for (size_t i = 0; i < expected_levels.size(); i++) {
      // level == -1 means the level should be ignored.
      if (expected_levels[i] == actual_levels[i] || expected_levels[i] == -1)
        continue;

      printf("LEVELS %s%s\n",
             DiffString(actual_levels, expected_levels).c_str(),
             error_context.str().c_str());
      level_failures_++;
      break;
    }
  }
  runs.DeleteRuns();
}

TEST(BidiResolver, DISABLED_BidiTest_txt) {
  BidiTestRunner runner;
  // Blink's Unicode Bidi Algorithm (UBA) doesn't yet support the
  // new isolate directives from Unicode 6.3:
  // http://www.unicode.org/reports/tr9/#Explicit_Directional_Isolates
  runner.SkipTestsWith(0x2066);  // LRI
  runner.SkipTestsWith(0x2067);  // RLI
  runner.SkipTestsWith(0x2068);  // FSI
  runner.SkipTestsWith(0x2069);  // PDI

  std::string bidi_test_path = "BidiTest.txt";
  std::ifstream bidi_test_file(bidi_test_path.c_str());
  EXPECT_TRUE(bidi_test_file.is_open());
  bidi_test::Harness<BidiTestRunner> harness(runner);
  harness.Parse(bidi_test_file);
  bidi_test_file.close();

  if (runner.tests_skipped_)
    LOG(WARNING) << "WARNING: Skipped " << runner.tests_skipped_ << " tests.";
  LOG(INFO) << "Ran " << runner.tests_run_
            << " tests: " << runner.level_failures_ << " level failures "
            << runner.order_failures_ << " order failures.";

  // The unittest harness only pays attention to GTest output, so we verify
  // that the tests behaved as expected:
  EXPECT_EQ(352098u, runner.tests_run_);
  EXPECT_EQ(418143u, runner.tests_skipped_);
  EXPECT_EQ(0u, runner.ignored_char_failures_);
  EXPECT_EQ(44882u, runner.level_failures_);
  EXPECT_EQ(19151u, runner.order_failures_);
}

TEST(BidiResolver, DISABLED_BidiCharacterTest_txt) {
  BidiTestRunner runner;
  // Blink's Unicode Bidi Algorithm (UBA) doesn't yet support the
  // new isolate directives from Unicode 6.3:
  // http://www.unicode.org/reports/tr9/#Explicit_Directional_Isolates
  runner.SkipTestsWith(0x2066);  // LRI
  runner.SkipTestsWith(0x2067);  // RLI
  runner.SkipTestsWith(0x2068);  // FSI
  runner.SkipTestsWith(0x2069);  // PDI

  std::string bidi_test_path = "BidiCharacterTest.txt";
  std::ifstream bidi_test_file(bidi_test_path.c_str());
  EXPECT_TRUE(bidi_test_file.is_open());
  bidi_test::CharacterHarness<BidiTestRunner> harness(runner);
  harness.Parse(bidi_test_file);
  bidi_test_file.close();

  if (runner.tests_skipped_)
    LOG(WARNING) << "WARNING: Skipped " << runner.tests_skipped_ << " tests.";
  LOG(INFO) << "Ran " << runner.tests_run_
            << " tests: " << runner.level_failures_ << " level failures "
            << runner.order_failures_ << " order failures.";

  EXPECT_EQ(91660u, runner.tests_run_);
  EXPECT_EQ(39u, runner.tests_skipped_);
  EXPECT_EQ(0u, runner.ignored_char_failures_);
  EXPECT_EQ(14533u, runner.level_failures_);
  EXPECT_EQ(14533u, runner.order_failures_);
}

}  // namespace blink
