/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef AAPT_TEST_COMMON_H
#define AAPT_TEST_COMMON_H

#include <iostream>

#include "android-base/logging.h"
#include "android-base/macros.h"
#include "androidfw/ConfigDescription.h"
#include "androidfw/StringPiece.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include "Debug.h"
#include "ResourceTable.h"
#include "ResourceUtils.h"
#include "ResourceValues.h"
#include "ValueVisitor.h"
#include "io/File.h"
#include "process/IResourceTableConsumer.h"

namespace aapt {
namespace test {

android::IDiagnostics* GetDiagnostics();

inline ResourceName ParseNameOrDie(android::StringPiece str) {
  ResourceNameRef ref;
  CHECK(ResourceUtils::ParseResourceName(str, &ref)) << "invalid resource name: " << str;
  return ref.ToResourceName();
}

inline android::ConfigDescription ParseConfigOrDie(android::StringPiece str) {
  android::ConfigDescription config;
  CHECK(android::ConfigDescription::Parse(str, &config)) << "invalid configuration: " << str;
  return config;
}

template <typename T = Value>
T* GetValueForConfigAndProduct(ResourceTable* table, android::StringPiece res_name,
                               const android::ConfigDescription& config,
                               android::StringPiece product) {
  std::optional<ResourceTable::SearchResult> result = table->FindResource(ParseNameOrDie(res_name));
  if (result) {
    ResourceConfigValue* config_value = result.value().entry->FindValue(config, product);
    if (config_value) {
      return ValueCast<T>(config_value->value.get());
    }
  }
  return nullptr;
}

template <>
Value* GetValueForConfigAndProduct<Value>(ResourceTable* table, android::StringPiece res_name,
                                          const android::ConfigDescription& config,
                                          android::StringPiece product);

template <typename T = Value>
T* GetValueForConfig(ResourceTable* table, android::StringPiece res_name,
                     const android::ConfigDescription& config) {
  return GetValueForConfigAndProduct<T>(table, res_name, config, {});
}

template <typename T = Value>
T* GetValue(ResourceTable* table, android::StringPiece res_name) {
  return GetValueForConfig<T>(table, res_name, {});
}

class TestFile : public io::IFile {
 public:
  explicit TestFile(android::StringPiece path) : source_(path) {
  }

  std::unique_ptr<io::IData> OpenAsData() override {
    return {};
  }

  std::unique_ptr<android::InputStream> OpenInputStream() override {
    return OpenAsData();
  }

  const android::Source& GetSource() const override {
    return source_;
  }

  bool GetModificationTime(struct tm* buf) const override {
    return false;
  };

 private:
  DISALLOW_COPY_AND_ASSIGN(TestFile);

  android::Source source_;
};

}  // namespace test

// Workaround gtest bug (https://github.com/google/googletest/issues/443)
// that does not select base class operator<< for derived class T.
template <typename T>
typename std::enable_if<std::is_base_of<Value, T>::value, std::ostream&>::type operator<<(
    std::ostream& out, const T& value) {
  value.Print(&out);
  return out;
}

template std::ostream& operator<<<Item>(std::ostream&, const Item&);
template std::ostream& operator<<<Reference>(std::ostream&, const Reference&);
template std::ostream& operator<<<Id>(std::ostream&, const Id&);
template std::ostream& operator<<<RawString>(std::ostream&, const RawString&);
template std::ostream& operator<<<String>(std::ostream&, const String&);
template std::ostream& operator<<<StyledString>(std::ostream&, const StyledString&);
template std::ostream& operator<<<FileReference>(std::ostream&, const FileReference&);
template std::ostream& operator<<<BinaryPrimitive>(std::ostream&, const BinaryPrimitive&);
template std::ostream& operator<<<Attribute>(std::ostream&, const Attribute&);
template std::ostream& operator<<<Style>(std::ostream&, const Style&);
template std::ostream& operator<<<Array>(std::ostream&, const Array&);
template std::ostream& operator<<<Plural>(std::ostream&, const Plural&);

// Add a print method to Maybe.
template <typename T>
void PrintTo(const std::optional<T>& value, std::ostream* out) {
  if (value) {
    *out << ::testing::PrintToString(value.value());
  } else {
    *out << "Nothing";
  }
}

namespace test {

MATCHER_P(StrEq, a,
          std::string(negation ? "isn't" : "is") + " equal to " +
              ::testing::PrintToString(android::StringPiece16(a))) {
  return android::StringPiece16(arg) == a;
}

template <typename T>
class ValueEqImpl : public ::testing::MatcherInterface<T> {
 public:
  explicit ValueEqImpl(const Value* expected) : expected_(expected) {
  }

  bool MatchAndExplain(T x, ::testing::MatchResultListener* listener) const override {
    return expected_->Equals(&x);
  }

  void DescribeTo(::std::ostream* os) const override {
    *os << "is equal to " << *expected_;
  }

  void DescribeNegationTo(::std::ostream* os) const override {
    *os << "is not equal to " << *expected_;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ValueEqImpl);

  const Value* expected_;
};

template <typename TValue>
class ValueEqMatcher {
 public:
  // NOLINTNEXTLINE(google-explicit-constructor)
  ValueEqMatcher(TValue expected) : expected_(std::move(expected)) {
  }

  template <typename T>
  // NOLINTNEXTLINE(google-explicit-constructor)
  operator ::testing::Matcher<T>() const {
    return ::testing::Matcher<T>(new ValueEqImpl<T>(&expected_));
  }

 private:
  TValue expected_;
};

template <typename TValue>
class ValueEqPointerMatcher {
 public:
  // NOLINTNEXTLINE(google-explicit-constructor)
  ValueEqPointerMatcher(const TValue* expected) : expected_(expected) {
  }

  template <typename T>
  // NOLINTNEXTLINE(google-explicit-constructor)
  operator ::testing::Matcher<T>() const {
    return ::testing::Matcher<T>(new ValueEqImpl<T>(expected_));
  }

 private:
  const TValue* expected_;
};

template <typename TValue,
          typename = typename std::enable_if<!std::is_pointer<TValue>::value, void>::type>
inline ValueEqMatcher<TValue> ValueEq(TValue value) {
  return ValueEqMatcher<TValue>(std::move(value));
}

template <typename TValue>
inline ValueEqPointerMatcher<TValue> ValueEq(const TValue* value) {
  return ValueEqPointerMatcher<TValue>(value);
}

MATCHER_P(StrValueEq, a,
          std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) {
  return *(arg.value) == a;
}

MATCHER_P(HasValue, name,
          std::string(negation ? "does not have" : "has") + " value " +
              ::testing::PrintToString(name)) {
  return GetValueForConfig<Value>(&(*arg), name, {}) != nullptr;
}

MATCHER_P2(HasValue, name, config,
           std::string(negation ? "does not have" : "has") + " value " +
               ::testing::PrintToString(name) + " for config " + ::testing::PrintToString(config)) {
  return GetValueForConfig<Value>(&(*arg), name, config) != nullptr;
}

}  // namespace test
}  // namespace aapt

#endif /* AAPT_TEST_COMMON_H */
