// Copyright 2020 The Tint Authors.
//
// 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 SRC_CASTABLE_H_
#define SRC_CASTABLE_H_

#include <cstdint>
#include <type_traits>
#include <utility>

namespace tint {

/// Helper macro to instantiate the ClassID for `CLASS`.
#define TINT_INSTANTIATE_CLASS_ID(CLASS) \
  template <>                            \
  const char ::tint::ClassID::Unique<CLASS>::token = 0

/// ClassID represents a unique, comparable identifier for a C++ type.
class ClassID {
 private:
  /// Helper template that holds a single static field, which is used by Of()
  /// to obtain a unique identifier by taking the field's address.
  template <typename T>
  struct Unique {
    static const char token;
  };

 public:
  /// @returns the unique ClassID for the type T.
  template <typename T>
  static ClassID Of() {
    // Take the address of a static variable to produce a unique identifier for
    // the type T.
    return ClassID{reinterpret_cast<uintptr_t>(&Unique<T>::token)};
  }

  /// Equality operator
  /// @param rhs the ClassID to compare against
  /// @returns true if this ClassID is equal to `rhs`
  inline bool operator==(ClassID& rhs) const { return id == rhs.id; }

 private:
  inline explicit ClassID(uintptr_t v) : id(v) {}

  const uintptr_t id;
};

/// CastableBase is the base class for all Castable objects.
/// It is not encouraged to directly derive from CastableBase without using the
/// Castable helper template.
/// @see Castable
class CastableBase {
 public:
  /// Copy constructor
  CastableBase(const CastableBase&) = default;

  /// Move constructor
  CastableBase(CastableBase&&) = default;

  virtual ~CastableBase() = default;

  /// @returns true if this object is of, or derives from a class with the
  /// ClassID `id`.
  /// @param id the ClassID to test for
  virtual bool Is(ClassID id) const;

  /// @returns true if this object is of, or derives from the class `TO`
  template <typename TO>
  bool Is() const {
    using FROM = CastableBase;
    constexpr const bool downcast = std::is_base_of<FROM, TO>::value;
    constexpr const bool upcast = std::is_base_of<TO, FROM>::value;
    constexpr const bool nocast = std::is_same<FROM, TO>::value;
    static_assert(upcast || downcast || nocast, "impossible cast");

    if (upcast || nocast) {
      return true;
    }

    return Is(ClassID::Of<TO>());
  }

  /// @returns this object dynamically cast to the type `TO` or `nullptr` if
  /// this object does not derive from `TO`.
  template <typename TO>
  inline TO* As() {
    return Is<TO>() ? static_cast<TO*>(this) : nullptr;
  }

  /// @returns this object dynamically cast to the type `TO` or `nullptr` if
  /// this object does not derive from `TO`.
  template <typename TO>
  inline const TO* As() const {
    return Is<TO>() ? static_cast<const TO*>(this) : nullptr;
  }

 protected:
  CastableBase() = default;
};

/// Castable is a helper to derive `CLASS` from `BASE`, automatically
/// implementing the Is() and As() methods, along with a #Base type alias.
///
/// Example usage:
///
/// ```
/// class Animal : public Castable<Animal> {};
///
/// class Sheep : public Castable<Sheep, Animal> {};
///
/// Sheep* cast_to_sheep(Animal* animal) {
///    // You can query whether a Castable is of the given type with Is<T>():
///    printf("animal is a sheep? %s", animal->Is<Sheep>() ? "yes" : "no");
///
///    // You can always just try the cast with As<T>().
///    // If the object is not of the correct type, As<T>() will return nullptr:
///    return animal->As<Sheep>();
/// }
/// ```
template <typename CLASS, typename BASE = CastableBase>
class Castable : public BASE {
 public:
  // Inherit the `BASE` class constructors.
  using BASE::BASE;

  /// A type alias for `CLASS` to easily access the `BASE` class members.
  /// Base actually aliases to the Castable instead of `BASE` so that you can
  /// use Base in the `CLASS` constructor.
  using Base = Castable;

  /// @returns true if this object is of, or derives from a class with the
  /// ClassID `id`.
  /// @param id the ClassID to test for
  bool Is(ClassID id) const override {
    return ClassID::Of<CLASS>() == id || BASE::Is(id);
  }

  /// @returns true if this object is of, or derives from the class `TO`
  template <typename TO>
  bool Is() const {
    using FROM = Castable;
    constexpr const bool downcast = std::is_base_of<FROM, TO>::value;
    constexpr const bool upcast = std::is_base_of<TO, FROM>::value;
    constexpr const bool nocast = std::is_same<FROM, TO>::value;
    static_assert(upcast || downcast || nocast, "impossible cast");

    if (upcast || nocast) {
      return true;
    }

    return Is(ClassID::Of<TO>());
  }

  /// @returns this object dynamically cast to the type `TO` or `nullptr` if
  /// this object does not derive from `TO`.
  template <typename TO>
  inline TO* As() {
    return Is<TO>() ? static_cast<TO*>(this) : nullptr;
  }

  /// @returns this object dynamically cast to the type `TO` or `nullptr` if
  /// this object does not derive from `TO`.
  template <typename TO>
  inline const TO* As() const {
    return Is<TO>() ? static_cast<const TO*>(this) : nullptr;
  }
};

/// As() dynamically casts `obj` to the target type `TO`.
/// @returns the cast object, or nullptr if `obj` is `nullptr` or not of the
/// type `TO`.
/// @param obj the object to cast
template <typename TO, typename FROM>
inline TO* As(FROM* obj) {
  if (obj == nullptr) {
    return nullptr;
  }
  return obj->template As<TO>();
}

}  // namespace tint

#endif  // SRC_CASTABLE_H_
