/*
 * 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_MAYBE_H
#define AAPT_MAYBE_H

#include <type_traits>
#include <utility>

#include "android-base/logging.h"

#include "util/TypeTraits.h"

namespace aapt {

/**
 * Either holds a valid value of type T, or holds Nothing.
 * The value is stored inline in this structure, so no
 * heap memory is used when creating a Maybe<T> object.
 */
template <typename T>
class Maybe {
 public:
  /**
   * Construct Nothing.
   */
  Maybe();

  ~Maybe();

  Maybe(const Maybe& rhs);

  template <typename U>
  Maybe(const Maybe<U>& rhs);  // NOLINT(google-explicit-constructor)

  Maybe(Maybe&& rhs) noexcept;

  template <typename U>
  Maybe(Maybe<U>&& rhs);  // NOLINT(google-explicit-constructor)

  Maybe& operator=(const Maybe& rhs);

  template <typename U>
  Maybe& operator=(const Maybe<U>& rhs);

  Maybe& operator=(Maybe&& rhs) noexcept;

  template <typename U>
  Maybe& operator=(Maybe<U>&& rhs);

  /**
   * Construct a Maybe holding a value.
   */
  Maybe(const T& value);  // NOLINT(google-explicit-constructor)

  /**
   * Construct a Maybe holding a value.
   */
  Maybe(T&& value);  // NOLINT(google-explicit-constructor)

  /**
   * True if this holds a value, false if
   * it holds Nothing.
   */
  explicit operator bool() const;

  /**
   * Gets the value if one exists, or else
   * panics.
   */
  T& value();

  /**
   * Gets the value if one exists, or else
   * panics.
   */
  const T& value() const;

  T value_or_default(const T& def) const;

 private:
  template <typename U>
  friend class Maybe;

  template <typename U>
  Maybe& copy(const Maybe<U>& rhs);

  template <typename U>
  Maybe& move(Maybe<U>&& rhs);

  void destroy();

  bool nothing_;

  typename std::aligned_storage<sizeof(T), alignof(T)>::type storage_;
};

template <typename T>
Maybe<T>::Maybe() : nothing_(true) {}

template <typename T>
Maybe<T>::~Maybe() {
  if (!nothing_) {
    destroy();
  }
}

template <typename T>
Maybe<T>::Maybe(const Maybe& rhs) : nothing_(rhs.nothing_) {
  if (!rhs.nothing_) {
    new (&storage_) T(reinterpret_cast<const T&>(rhs.storage_));
  }
}

template <typename T>
template <typename U>
Maybe<T>::Maybe(const Maybe<U>& rhs) : nothing_(rhs.nothing_) {
  if (!rhs.nothing_) {
    new (&storage_) T(reinterpret_cast<const U&>(rhs.storage_));
  }
}

template <typename T>
Maybe<T>::Maybe(Maybe&& rhs) noexcept : nothing_(rhs.nothing_) {
  if (!rhs.nothing_) {
    rhs.nothing_ = true;

    // Move the value from rhs.
    new (&storage_) T(std::move(reinterpret_cast<T&>(rhs.storage_)));
    rhs.destroy();
  }
}

template <typename T>
template <typename U>
Maybe<T>::Maybe(Maybe<U>&& rhs) : nothing_(rhs.nothing_) {
  if (!rhs.nothing_) {
    rhs.nothing_ = true;

    // Move the value from rhs.
    new (&storage_) T(std::move(reinterpret_cast<U&>(rhs.storage_)));
    rhs.destroy();
  }
}

template <typename T>
inline Maybe<T>& Maybe<T>::operator=(const Maybe& rhs) {
  // Delegate to the actual assignment.
  return copy(rhs);
}

template <typename T>
template <typename U>
inline Maybe<T>& Maybe<T>::operator=(const Maybe<U>& rhs) {
  return copy(rhs);
}

template <typename T>
template <typename U>
Maybe<T>& Maybe<T>::copy(const Maybe<U>& rhs) {
  if (nothing_ && rhs.nothing_) {
    // Both are nothing, nothing to do.
    return *this;
  } else if (!nothing_ && !rhs.nothing_) {
    // We both are something, so assign rhs to us.
    reinterpret_cast<T&>(storage_) = reinterpret_cast<const U&>(rhs.storage_);
  } else if (nothing_) {
    // We are nothing but rhs is something.
    nothing_ = rhs.nothing_;

    // Copy the value from rhs.
    new (&storage_) T(reinterpret_cast<const U&>(rhs.storage_));
  } else {
    // We are something but rhs is nothing, so destroy our value.
    nothing_ = rhs.nothing_;
    destroy();
  }
  return *this;
}

template <typename T>
inline Maybe<T>& Maybe<T>::operator=(Maybe&& rhs) noexcept {
  // Delegate to the actual assignment.
  return move(std::forward<Maybe<T>>(rhs));
}

template <typename T>
template <typename U>
inline Maybe<T>& Maybe<T>::operator=(Maybe<U>&& rhs) {
  return move(std::forward<Maybe<U>>(rhs));
}

template <typename T>
template <typename U>
Maybe<T>& Maybe<T>::move(Maybe<U>&& rhs) {
  if (nothing_ && rhs.nothing_) {
    // Both are nothing, nothing to do.
    return *this;
  } else if (!nothing_ && !rhs.nothing_) {
    // We both are something, so move assign rhs to us.
    rhs.nothing_ = true;
    reinterpret_cast<T&>(storage_) =
        std::move(reinterpret_cast<U&>(rhs.storage_));
    rhs.destroy();
  } else if (nothing_) {
    // We are nothing but rhs is something.
    nothing_ = false;
    rhs.nothing_ = true;

    // Move the value from rhs.
    new (&storage_) T(std::move(reinterpret_cast<U&>(rhs.storage_)));
    rhs.destroy();
  } else {
    // We are something but rhs is nothing, so destroy our value.
    nothing_ = true;
    destroy();
  }
  return *this;
}

template <typename T>
Maybe<T>::Maybe(const T& value) : nothing_(false) {
  new (&storage_) T(value);
}

template <typename T>
Maybe<T>::Maybe(T&& value) : nothing_(false) {
  new (&storage_) T(std::forward<T>(value));
}

template <typename T>
Maybe<T>::operator bool() const {
  return !nothing_;
}

template <typename T>
T& Maybe<T>::value() {
  CHECK(!nothing_) << "Maybe<T>::value() called on Nothing";
  return reinterpret_cast<T&>(storage_);
}

template <typename T>
const T& Maybe<T>::value() const {
  CHECK(!nothing_) << "Maybe<T>::value() called on Nothing";
  return reinterpret_cast<const T&>(storage_);
}

template <typename T>
T Maybe<T>::value_or_default(const T& def) const {
  if (nothing_) {
    return def;
  }
  return reinterpret_cast<const T&>(storage_);
}

template <typename T>
void Maybe<T>::destroy() {
  reinterpret_cast<T&>(storage_).~T();
}

template <typename T>
inline Maybe<typename std::remove_reference<T>::type> make_value(T&& value) {
  return Maybe<typename std::remove_reference<T>::type>(std::forward<T>(value));
}

template <typename T>
inline Maybe<T> make_nothing() {
  return Maybe<T>();
}

// Define the == operator between Maybe<T> and Maybe<U> only if the operator T == U is defined.
// That way the compiler will show an error at the callsite when comparing two Maybe<> objects
// whose inner types can't be compared.
template <typename T, typename U>
typename std::enable_if<has_eq_op<T, U>::value, bool>::type operator==(const Maybe<T>& a,
                                                                       const Maybe<U>& b) {
  if (a && b) {
    return a.value() == b.value();
  } else if (!a && !b) {
    return true;
  }
  return false;
}

template <typename T, typename U>
typename std::enable_if<has_eq_op<T, U>::value, bool>::type operator==(const Maybe<T>& a,
                                                                       const U& b) {
  return a ? a.value() == b : false;
}

// Same as operator== but negated.
template <typename T, typename U>
typename std::enable_if<has_eq_op<T, U>::value, bool>::type operator!=(const Maybe<T>& a,
                                                                       const Maybe<U>& b) {
  return !(a == b);
}

template <typename T, typename U>
typename std::enable_if<has_lt_op<T, U>::value, bool>::type operator<(const Maybe<T>& a,
                                                                      const Maybe<U>& b) {
  if (a && b) {
    return a.value() < b.value();
  } else if (!a && !b) {
    return false;
  }
  return !a;
}

}  // namespace aapt

#endif  // AAPT_MAYBE_H
