// Copyright 2021 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 ZXTEST_CPP_STREAMS_HELPER_H_
#define ZXTEST_CPP_STREAMS_HELPER_H_

#include <iostream>
#include <optional>
#include <sstream>

#include <zxtest/base/assertion.h>
#include <zxtest/base/types.h>

DECLARE_HAS_MEMBER_FN_WITH_SIGNATURE(has_status_value, status_value, zx_status_t (C::*)() const);
DECLARE_HAS_MEMBER_FN_WITH_SIGNATURE(has_status, status, zx_status_t (C::*)() const);

#define LIB_ZXTEST_RETURN_TAG_true return Tag()&
#define LIB_ZXTEST_RETURN_TAG_false
#define LIB_ZXTEST_RETURN_TAG(val) LIB_ZXTEST_RETURN_TAG_##val

template <typename T>
zx_status_t GetStatus(const T& status) {
  if constexpr (has_status_value_v<T>) {
    return status.status_value();
  } else if constexpr (has_status_v<T>) {
    return status.status();
  } else {
    return status;
  }
}

struct Tag {};

class StreamableBase {
 public:
  StreamableBase(const zxtest::SourceLocation location)
      : stream_(std::stringstream("")), location_(location) {}

  // Lower precedence operator that returns void, such that the following
  // expressions are valid in functions that return void:
  //
  //  return Tag{} & StreamableBase{};
  //  return Tag{} & StreamableBase{} << "Stream operators are higher precedence than &";
  //
  friend void operator&(Tag, const StreamableBase&) {}

  template <typename T>
  StreamableBase& operator<<(T t) {
    stream_ << t;
    return *this;
  }

 protected:
  std::stringstream stream_;
  const zxtest::SourceLocation location_;
};

class StreamableFail : public StreamableBase {
 public:
  StreamableFail(const zxtest::SourceLocation location, bool is_fatal,
                 const cpp20::span<zxtest::Message*> traces)
      : StreamableBase(location), is_fatal_(is_fatal), traces_(traces) {}

  virtual ~StreamableFail() {
    zxtest::Runner::GetInstance()->NotifyAssertion(
        zxtest::Assertion(stream_.str(), location_, is_fatal_, traces_));
  }

 private:
  bool is_fatal_ = false;
  cpp20::span<zxtest::Message*> traces_;
};

class StreamableAssertion : public StreamableBase {
 public:
  template <typename Actual, typename Expected, typename CompareOp, typename PrintActual,
            typename PrintExpected>
  StreamableAssertion(const Actual& actual, const Expected& expected, const char* actual_symbol,
                      const char* expected_symbol, const zxtest::SourceLocation location,
                      bool is_fatal, const CompareOp& compare, const PrintActual& print_actual,
                      const PrintExpected& print_expected,
                      const cpp20::span<zxtest::Message*> traces)
      : StreamableBase(location),
        actual_symbol_(actual_symbol),
        expected_symbol_(expected_symbol),
        is_fatal_(is_fatal),
        traces_(traces) {
    actual_value_ = print_actual(actual);
    expected_value_ = print_expected(expected);
    is_triggered_ = !compare(actual, expected);
  }

  ~StreamableAssertion() {
    if (is_triggered_) {
      zxtest::Runner::GetInstance()->NotifyAssertion(zxtest::Assertion(
          stream_.str(), expected_symbol_.value(), expected_value_.value(), actual_symbol_.value(),
          actual_value_.value(), location_, is_fatal_, traces_));
    }
  }

  bool IsTriggered() { return is_triggered_; }

 private:
  std::optional<fbl::String> actual_value_;
  std::optional<fbl::String> expected_value_;
  std::optional<const char*> actual_symbol_;
  std::optional<const char*> expected_symbol_;
  bool is_fatal_ = false;
  bool is_triggered_ = true;
  cpp20::span<zxtest::Message*> traces_;
};

class StreamableSkip : public StreamableBase {
 public:
  StreamableSkip(const zxtest::SourceLocation location) : StreamableBase(location) {}

  ~StreamableSkip() {
    zxtest::Message message(stream_.str(), location_);
    zxtest::Runner::GetInstance()->SkipCurrent(message);
  }
};

#endif  // ZXTEST_CPP_STREAMS_HELPER_H_
