// Copyright 2019 The Fuchsia 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 "src/lib/util/file_util.h"

#include <fstream>
#include <streambuf>
#include <string>

#include "src/lib/util/status_builder.h"
#include "src/logging.h"
#include "src/public/lib/status.h"
#include "src/public/lib/status_codes.h"
#include "third_party/abseil-cpp/absl/strings/ascii.h"
#include "third_party/abseil-cpp/absl/strings/escaping.h"

namespace cobalt::util {

namespace {
constexpr int kMaxFileSize = 100000;
}

lib::statusor::StatusOr<std::string> ReadTextFile(const Path& file_path) {
  std::string file_contents;
  if (file_path.get().empty()) {
    return util::StatusBuilder(StatusCode::INVALID_ARGUMENT, "ReadTextFile: file_path is empty.")
        .Build();
  }
  std::ifstream stream(file_path.get(), std::ifstream::in);
  if (!stream.good()) {
    return util::StatusBuilder(StatusCode::NOT_FOUND, "Unable to open file")
        .WithContexts(file_path)
        .Build();
  }
  stream.seekg(0, std::ios::end);
  if (!stream.good()) {
    return util::StatusBuilder(StatusCode::INTERNAL, "Error reading file")
        .WithContexts(file_path)
        .Build();
  }
  int64_t file_size = stream.tellg();
  if (file_size == 0) {
    return std::string("");
  }
  // Don't try to read a file that's too big.
  if (!stream.good() || file_size < 0 || file_size > kMaxFileSize) {
    return util::StatusBuilder(StatusCode::FAILED_PRECONDITION, "Invalid file length")
        .WithContexts(file_path)
        .Build();
  }
  file_contents.reserve(static_cast<uint64_t>(file_size));

  stream.seekg(0, std::ios::beg);
  if (!stream.good()) {
    return util::StatusBuilder(StatusCode::NOT_FOUND, "Error reading file")
        .WithContexts(file_path)
        .Build();
  }
  file_contents.assign((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
  if (!stream.good()) {
    return util::StatusBuilder(StatusCode::NOT_FOUND, "Error reading file")
        .WithContexts(file_path)
        .Build();
  }
  VLOG(3) << "Successfully read file at " << file_path;
  return file_contents;
}

lib::statusor::StatusOr<std::string> ReadNonEmptyTextFile(const Path& file_path) {
  auto read_file_result = ReadTextFile(file_path);
  if (!read_file_result.ok()) {
    return read_file_result;
  }

  if (read_file_result.ValueOrDie().empty()) {
    return util::StatusBuilder(StatusCode::FAILED_PRECONDITION, "File was empty")
        .WithContexts(file_path)
        .Build();
  }

  return read_file_result;
}

lib::statusor::StatusOr<std::string> ReadNonEmptyTextFile(const std::string& file_path) {
  return ReadNonEmptyTextFile(Path(file_path));
}

lib::statusor::StatusOr<std::string> ReadHexFile(const Path& file_path) {
  auto read_file_result = ReadNonEmptyTextFile(file_path);
  if (!read_file_result.ok()) {
    return read_file_result;
  }

  auto hex = absl::StripAsciiWhitespace(read_file_result.ValueOrDie());
  if (hex.size() % 2 == 1) {
    return util::StatusBuilder(StatusCode::FAILED_PRECONDITION, "Hex file has invalid size")
        .WithContexts(file_path)
        .Build();
  }

  if (std::find_if_not(hex.begin(), hex.end(), absl::ascii_isxdigit) != hex.end()) {
    return util::StatusBuilder(StatusCode::FAILED_PRECONDITION, "Hex file has non-hex characters")
        .WithContexts(file_path)
        .Build();
  }

  return absl::HexStringToBytes(hex);
}

std::string ReadHexFileOrDefault(const Path& file_path, const std::string& default_string) {
  auto read_hex_file_result = ReadHexFile(file_path);
  if (!read_hex_file_result.ok()) {
    VLOG(1) << "Failed to read hex file: " << read_hex_file_result.status();
    return default_string;
  }

  return read_hex_file_result.ValueOrDie();
}

std::string ReadHexFileOrDefault(const std::string& file_path, const std::string& default_string) {
  return ReadHexFileOrDefault(Path(file_path), default_string);
}

}  // namespace cobalt::util
