// Copyright 2015 The Weave 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 <weave/error.h>

#include <base/logging.h>
#include <base/strings/stringprintf.h>

namespace weave {

namespace {
inline void LogError(const tracked_objects::Location& location,
                     const std::string& domain,
                     const std::string& code,
                     const std::string& message) {
  // Use logging::LogMessage() directly instead of LOG(ERROR) to substitute
  // the current error location with the location passed in to the Error object.
  // This way the log will contain the actual location of the error, and not
  // as if it always comes from chromeos/errors/error.cc(22).
  logging::LogMessage(location.file_name(), location.line_number(),
                      logging::LOG_ERROR)
          .stream()
      << location.function_name() << "(...): "
      << "Domain=" << domain << ", Code=" << code << ", Message=" << message;
}
}  // anonymous namespace

ErrorPtr Error::Create(const tracked_objects::Location& location,
                       const std::string& domain,
                       const std::string& code,
                       const std::string& message) {
  return Create(location, domain, code, message, ErrorPtr());
}

ErrorPtr Error::Create(const tracked_objects::Location& location,
                       const std::string& domain,
                       const std::string& code,
                       const std::string& message,
                       ErrorPtr inner_error) {
  LogError(location, domain, code, message);
  return ErrorPtr(
      new Error(location, domain, code, message, std::move(inner_error)));
}

void Error::AddTo(ErrorPtr* error,
                  const tracked_objects::Location& location,
                  const std::string& domain,
                  const std::string& code,
                  const std::string& message) {
  if (error) {
    *error = Create(location, domain, code, message, std::move(*error));
  } else {
    // Create already logs the error, but if |error| is nullptr,
    // we still want to log the error...
    LogError(location, domain, code, message);
  }
}

void Error::AddToPrintf(ErrorPtr* error,
                        const tracked_objects::Location& location,
                        const std::string& domain,
                        const std::string& code,
                        const char* format,
                        ...) {
  va_list ap;
  va_start(ap, format);
  std::string message = base::StringPrintV(format, ap);
  va_end(ap);
  AddTo(error, location, domain, code, message);
}

ErrorPtr Error::Clone() const {
  ErrorPtr inner_error = inner_error_ ? inner_error_->Clone() : nullptr;
  return ErrorPtr(
      new Error(location_, domain_, code_, message_, std::move(inner_error)));
}

bool Error::HasDomain(const std::string& domain) const {
  return FindErrorOfDomain(this, domain) != nullptr;
}

bool Error::HasError(const std::string& domain, const std::string& code) const {
  return FindError(this, domain, code) != nullptr;
}

const Error* Error::GetFirstError() const {
  const Error* err = this;
  while (err->GetInnerError())
    err = err->GetInnerError();
  return err;
}

Error::Error(const tracked_objects::Location& location,
             const std::string& domain,
             const std::string& code,
             const std::string& message,
             ErrorPtr inner_error)
    : Error{tracked_objects::LocationSnapshot{location}, domain, code, message,
            std::move(inner_error)} {}

Error::Error(const tracked_objects::LocationSnapshot& location,
             const std::string& domain,
             const std::string& code,
             const std::string& message,
             ErrorPtr inner_error)
    : domain_(domain),
      code_(code),
      message_(message),
      location_(location),
      inner_error_(std::move(inner_error)) {}

const Error* Error::FindErrorOfDomain(const Error* error_chain_start,
                                      const std::string& domain) {
  while (error_chain_start) {
    if (error_chain_start->GetDomain() == domain)
      break;
    error_chain_start = error_chain_start->GetInnerError();
  }
  return error_chain_start;
}

const Error* Error::FindError(const Error* error_chain_start,
                              const std::string& domain,
                              const std::string& code) {
  while (error_chain_start) {
    if (error_chain_start->GetDomain() == domain &&
        error_chain_start->GetCode() == code)
      break;
    error_chain_start = error_chain_start->GetInnerError();
  }
  return error_chain_start;
}

}  // namespace weave
