/**
 * 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 "utility/textbased_test/TextBasedTestDriver.hpp"

#include <algorithm>
#include <cctype>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <istream>
#include <set>
#include <string>
#include <vector>

#include "utility/textbased_test/TextBasedTest.hpp"

#include "glog/logging.h"

namespace quickstep {

namespace {

static const char *kSameAsAboveString = "[same as above]";

/**
 * @brief Returns a newline-terminated line from \p is.
 *
 * @param is The istream object from which line characters are extracted.
 * @param line The string object to store the extracted line.
 * @return True if \p line is not empty.
 */
bool GetLineWithNewLineNotTrimmed(std::istream *is, std::string *line) {
  line->clear();

  std::istream::sentry se(*is, true);
  if (se) {
    std::streambuf* sb = is->rdbuf();
    for (;;) {
      const char c = sb->sgetc();
      switch (c) {
        case '\n':
          line->push_back(c);
          sb->sbumpc();
          return true;
        case '\r':
          *line += c;
          if (sb->snextc() == '\n') {
            line->push_back(sb->sgetc());
            sb->sbumpc();
          }
          return true;
        case EOF:
          is->setstate(std::ios_base::eofbit);
          if (line->empty()) {
            return false;
          }
          return true;
        default:
          line->push_back(c);
          sb->sbumpc();
      }
    }
  }

  return false;
}

}  // namespace

TextBasedTestDriver::TextBasedTestDriver(std::istream *input_stream, TextBasedTestRunner *test_runner)
    : input_stream_(input_stream),
      test_runner_(test_runner) {
  CHECK(input_stream_->good());
}

TextBasedTestDriver::~TextBasedTestDriver() {
  clearTestCases();
}

void TextBasedTestDriver::clearTestCases() {
  for (const TextBasedTestCase *test_case : test_cases_) {
    delete test_case;
  }
  test_cases_.clear();
}

std::vector<TextBasedTestCase*>* TextBasedTestDriver::populateAndReturnTestCases() {
  populateTestCases();
  return &test_cases_;
}

void TextBasedTestDriver::writeActualOutput(std::ostream *out) const {
  const TextBasedTestCase *previous_case = nullptr;
  for (const TextBasedTestCase *test_case : test_cases_) {
    if (previous_case != nullptr) {
      *out << "==" << std::endl;
    }
    *out << test_case->preceding_text;
    *out << test_case->input_text;
    *out << "--" << std::endl;
    if (previous_case != nullptr &&
        test_case->actual_output_text == previous_case->actual_output_text) {
      *out << kSameAsAboveString << std::endl;
    } else {
      *out << test_case->actual_output_text;
    }
    previous_case = test_case;
  }
}

void TextBasedTestDriver::writeActualOutputToFile(const std::string &output_filename) const {
  std::ofstream file_stream(output_filename);
  CHECK(file_stream.is_open()) << "Output file " << output_filename << " cannot be written to";
  writeActualOutput(&file_stream);
}

void TextBasedTestDriver::populateTestCases() {
  TextBasedTestCase *test_case = readNextTestCase();
  while (test_case != nullptr) {
    CHECK(!std::all_of(test_case->input_text.begin(), test_case->input_text.end(), ::isspace)) << "Input text is empty";
    test_cases_.push_back(test_case);
    test_case = readNextTestCase();
  }
}

TextBasedTestCase* TextBasedTestDriver::readNextTestCase() {
  if (input_stream_->eof()) {
    return nullptr;
  }

  std::string line;
  std::ostringstream test_input;
  std::ostringstream non_test_input;
  std::ostringstream test_output;

  // Read leading comments.
  while (GetLineWithNewLineNotTrimmed(input_stream_, &line)) {
    DCHECK(!line.empty());
    if (line.at(0) == '[') {
      break;
    }
    if (line.at(0) != '#') {
      if (!std::all_of(line.begin(), line.end(), ::isspace)) {
        break;
      }
    }
    non_test_input << line;
  }

  if (line.empty()) {
    // We are reaching the end.
    CHECK(input_stream_->eof());
    return nullptr;
  }

  // Read option specifications.
  std::set<std::string> options;
  std::set<std::string> default_options;
  if (line.at(0) == '[') {
    readOptions(line, &options, &default_options);
    non_test_input << line;
    while (GetLineWithNewLineNotTrimmed(input_stream_, &line)) {
      DCHECK(!line.empty());
      if (line.at(0) == '[') {
        readOptions(line, &options, &default_options);
      } else {
        if (!std::all_of(line.begin(), line.end(), ::isspace)) {
          break;
        }
      }
      non_test_input << line;
    }
  }

  if (!default_options.empty()) {
    default_options_ = std::move(default_options);
  }
  options.insert(default_options_.begin(), default_options_.end());

  CHECK(!line.empty() || IsInputOutputSeparator(line)) << "Has options but no input test text";
  test_input << line;

  while (GetLineWithNewLineNotTrimmed(input_stream_, &line)) {
    if (IsInputOutputSeparator(line)) {
      break;
    }
    test_input << line;
  }

  while (GetLineWithNewLineNotTrimmed(input_stream_, &line)) {
    if (IsTestCaseSeparator(line)) {
      break;
    }
    test_output << line;
  }

  if (test_output.str().compare(0, ::strlen(kSameAsAboveString), kSameAsAboveString) == 0) {
    CHECK(!test_cases_.empty()) << "Cannot specify \"same as above\" in the first test case";
    test_output.str("");
    test_output << test_cases_.back()->expected_output_text;
  }

  return new TextBasedTestCase(non_test_input.str(),
                               test_input.str(),
                               test_output.str(),
                               std::move(options),
                               test_runner_);
}

void TextBasedTestDriver::readOptions(const std::string &line,
                                      std::set<std::string> *options_out,
                                      std::set<std::string> *default_options_out) {
  DCHECK(!line.empty() && line.at(0) == '[') << line;
  std::string token;
  std::istringstream line_stream(line);
  line_stream.get();

  // Create a temporary vector to store the options in the current line.
  // The options cannot be directly inserted to <options_out> and
  // copy the content to <default_options_out> if default is specified,
  // because <options_out> may contain non-default options given in
  // preceding lines.
  std::vector<std::string> options;
  while (line_stream >> token) {
    size_t bracket_pos = token.find(']');
    if (bracket_pos != std::string::npos) {
      CHECK_EQ(bracket_pos + 1, token.size()) << "Cannot have text after options";
      if (token.size() > 1) {
        options.push_back(token.substr(0, bracket_pos));
      }
      break;
    }
    options.push_back(token);
  }

  CHECK(!(line_stream >> token)) << "Cannot have text after options";

  bool is_default = false;
  std::vector<std::string>::const_iterator start_it = options.begin();
  std::vector<std::string>::const_iterator end_it = options.end();
  if (start_it != end_it && *start_it == "default") {
    ++start_it;
    is_default = true;
  }

  CHECK(start_it != end_it) << "Has no options specified in the brackets";

  if (is_default) {
    default_options_out->insert(start_it, end_it);
  }

  while (start_it != end_it) {
    CHECK(isRegisteredOption(*start_it)) << "Option " << *start_it << " is not found";
    options_out->insert(*start_it);
    ++start_it;
  }
}

bool TextBasedTestDriver::IsInputOutputSeparator(const std::string &str) {
  if (str.size() > 1 && str.at(0) == '-' && str.at(1) == '-') {
    return true;
  }
  return false;
}

bool TextBasedTestDriver::IsTestCaseSeparator(const std::string &str) {
  if (str.size() > 1 && str.at(0) == '=' && str.at(1) == '=') {
    return true;
  }
  return false;
}

bool TextBasedTestDriver::isValidOption(const std::string &name) const {
  if (name.empty()) return false;

  for (const char c : name) {
    if (!std::isalnum(c) && c != '_') {
      return false;
    }
  }
  return true;
}

void TextBasedTestDriver::registerOptions(const std::vector<std::string> &option_names) {
  for (const std::string &option_name : option_names) {
    registerOption(option_name);
  }
}

void TextBasedTestDriver::registerOption(const std::string &option_name) {
  CHECK(isValidOption(option_name))
      << "Option " << option_name << " is not valid (must contain only alphanumeric characters and underscores)";
  registered_options_.insert(option_name);
}

bool TextBasedTestDriver::isRegisteredOption(const std::string &option_name) const {
  return registered_options_.find(option_name) != registered_options_.end();
}

}  // namespace quickstep
