// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "croslog/log_entry_reader.h"

#include <list>
#include <utility>

#include "base/optional.h"
#include "base/strings/string_util.h"

#include "croslog/log_parser_syslog.h"

namespace croslog {

LogEntryReader::LogEntryReader(base::FilePath log_file,
                               std::unique_ptr<LogParser> parser_in,
                               bool install_change_watcher)
    : file_path_(log_file),
      line_reader_(install_change_watcher ? LogLineReader::Backend::FILE_FOLLOW
                                          : LogLineReader::Backend::FILE),
      parser_(std::move(parser_in)) {
  line_reader_.OpenFile(std::move(log_file));
}

MaybeLogEntry LogEntryReader::GetPreviousEntry() {
  // If we have looked ahead, go back to the current position and invalidate the
  // cache.
  if (next_entry_.has_value()) {
    line_reader_.Backward();
    next_entry_.reset();
  }

  std::list<std::string> lines;
  // Reads preceding lines until a parsable line, which should be the first
  // line of log entry, comes.
  while (true) {
    base::Optional<std::string> line = line_reader_.Backward();
    if (!line.has_value()) {
      // No more entry
      return base::nullopt;
    }

    MaybeLogEntry entry = parser_->Parse(std::move(*line));
    if (entry.has_value()) {
      if (!lines.empty())
        entry->AppendLinesToMessage(lines);
      return entry;
    }
    lines.push_front(*line);
  }
}

MaybeLogEntry LogEntryReader::GetNextEntry() {
  MaybeLogEntry entry;
  if (!next_entry_.has_value()) {
    // Reads a next lines with skipping non-parsable lines.
    while (true) {
      base::Optional<std::string> line = line_reader_.Forward();
      if (!line.has_value()) {
        // No more entry
        return base::nullopt;
      }

      MaybeLogEntry maybe_entry = parser_->Parse(std::move(*line));
      if (!maybe_entry.has_value()) {
        // Parse failed. Go to the next line.
        continue;
      }

      entry.emplace(std::move(*maybe_entry));
      break;
    }
  } else {
    entry.emplace(std::move(*next_entry_));
    next_entry_.reset();
  }

  std::list<std::string> lines;
  // Reads succeeding lines until a parsable line, which should be the first
  // line of the next log entry, comes.
  while (true) {
    base::Optional<std::string> line = line_reader_.Forward();
    if (!line.has_value()) {
      // No more entry
      break;
    }

    MaybeLogEntry maybe_entry = parser_->Parse(std::move(*line));
    if (maybe_entry.has_value()) {
      next_entry_.emplace(std::move(*maybe_entry));
      break;
    }

    lines.push_back(std::move(*line));
  }

  entry->AppendLinesToMessage(lines);
  return entry;
}

void LogEntryReader::SetPositionLast() {
  line_reader_.SetPositionLast();
}

void LogEntryReader::AddObserver(LogLineReader::Observer* obs) {
  line_reader_.AddObserver(obs);
}

void LogEntryReader::RemoveObserver(LogLineReader::Observer* obs) {
  line_reader_.RemoveObserver(obs);
}

}  // namespace croslog
