// 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.

#ifndef SRC_DEVELOPER_FORENSICS_TESTING_GMATCHERS_H_
#define SRC_DEVELOPER_FORENSICS_TESTING_GMATCHERS_H_

#include <fuchsia/feedback/cpp/fidl.h>

#include <sstream>
#include <string>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "src/developer/forensics/feedback/attachments/types.h"
#include "src/developer/forensics/utils/errors.h"
#include "src/lib/fsl/vmo/strings.h"

namespace forensics {
namespace internal {

// Allows expectations to be set on AttachmentValue. Needed because values can't easily be compared
// for equality due to the move-only nature of AttachmentValue.
class AttachmentValueMatcher
    : public ::testing::MatcherInterface<const feedback::AttachmentValue&> {
 public:
  using is_gtest_matcher = void;

  AttachmentValueMatcher(std::string value) : value_(std::move(value)), error_(std::nullopt) {}
  AttachmentValueMatcher(const Error error) : value_(std::nullopt), error_(error) {}
  AttachmentValueMatcher(std::string value, const Error error)
      : value_(std::move(value)), error_(error) {}

  bool MatchAndExplain(const feedback::AttachmentValue& val,
                       ::testing::MatchResultListener* listener) const override {
    const bool value_matches =
        val.HasValue() == value_.has_value() && (!val.HasValue() || val.Value() == *value_);
    const bool error_matches =
        val.HasError() == error_.has_value() && (!val.HasError() || val.Error() == *error_);

    if (value_matches && error_matches) {
      return true;
    }

    *listener << "expected attachment value " << Describe();
    return false;
  }

  void DescribeTo(::std::ostream* os) const override { *os << Describe(); }

  void DescribeNegationTo(::std::ostream* os) const override { *os << " not " << Describe(); }

 private:
  std::string Describe() const {
    std::stringstream ss;
    if (value_.has_value()) {
      ss << "has a value \"" << *value_ << "\"";
    } else {
      ss << "does not have a value";
    }

    ss << " and ";

    if (error_.has_value()) {
      ss << "has an error \"" << ToString(*error_) << "\"";
    } else {
      ss << "does not have an error";
    }

    return ss.str();
  }

  std::optional<std::string> value_;
  std::optional<Error> error_;
};

// Compares two Attachment objects.
template <typename ResultListenerT>
bool DoAttachmentMatch(const fuchsia::feedback::Attachment& actual, const std::string& expected_key,
                       const std::string& expected_value, ResultListenerT* result_listener) {
  if (actual.key != expected_key) {
    *result_listener << "Expected key " << expected_key << ", got " << actual.key;
    return false;
  }

  std::string actual_value;
  if (!fsl::StringFromVmo(actual.value, &actual_value)) {
    *result_listener << "Cannot parse actual VMO for key " << actual.key << " to string";
    return false;
  }

  if (actual_value != expected_value) {
    *result_listener << "Expected value " << expected_value << ", got " << actual_value;
    return false;
  }

  return true;
}

// Compares two Annotation objects.
template <typename ResultListenerT>
bool DoAnnotationMatch(const fuchsia::feedback::Annotation& actual, const std::string& expected_key,
                       const std::string& expected_value, ResultListenerT* result_listener) {
  if (actual.key != expected_key) {
    *result_listener << "Expected key " << expected_key << ", got " << actual.key;
    return false;
  }

  if (actual.value != expected_value) {
    *result_listener << "Expected value " << expected_value << ", got " << actual.value;
    return false;
  }

  return true;
}

template <typename ResultListenerT>
bool DoStringBufferMatch(const fuchsia::mem::Buffer& actual, const std::string& expected,
                         ResultListenerT* result_listener) {
  std::string actual_value;
  if (!fsl::StringFromVmo(actual, &actual_value)) {
    *result_listener << "Cannot parse actual VMO to string";
    return false;
  }

  if (actual_value != expected) {
    return false;
  }

  return true;
}

}  // namespace internal

// Returns true if gMock |arg|.key matches |expected_key|.
MATCHER_P(MatchesKey, expected_key,
          "matches an element with key '" + std::string(expected_key) + "'") {
  return arg.key == expected_key;
}

// Returns true if gMock |arg|.key matches |expected_key| and str(|arg|.value) matches
// |expected_value|, assuming two Attachment objects.
MATCHER_P2(MatchesAttachment, expected_key, expected_value,
           "matches an attachment with key '" + std::string(expected_key) + "' and value '" +
               std::string(expected_value) + "'") {
  return internal::DoAttachmentMatch(arg, expected_key, expected_value, result_listener);
}

// Returns true if gMock |arg|.key matches |expected_key| and str(|arg|.value) matches
// |expected_value|, assuming two Annotation objects.
MATCHER_P2(MatchesAnnotation, expected_key, expected_value,
           "matches an annotation with key '" + std::string(expected_key) + "' and value '" +
               std::string(expected_value) + "'") {
  return internal::DoAnnotationMatch(arg, expected_key, expected_value, result_listener);
}

// Returns true if gMock str(|arg|) matches |expected|.
MATCHER_P(MatchesStringBuffer, expected, "'" + std::string(expected) + "'") {
  return internal::DoStringBufferMatch(arg, expected, result_listener);
}

MATCHER(HasValue, negation ? "is error" : "has value") {
  if (arg.HasValue()) {
    return true;
  }

  return false;
}

inline testing::Matcher<feedback::AttachmentValue> AttachmentValueIs(std::string data) {
  return internal::AttachmentValueMatcher(std::move(data));
}

inline testing::Matcher<feedback::AttachmentValue> AttachmentValueIs(const Error error) {
  return internal::AttachmentValueMatcher(error);
}

inline testing::Matcher<feedback::AttachmentValue> AttachmentValueIs(std::string data,
                                                                     const Error error) {
  return internal::AttachmentValueMatcher(std::move(data), error);
}

}  // namespace forensics

#endif  // SRC_DEVELOPER_FORENSICS_TESTING_GMATCHERS_H_
