// Copyright 2019 Google LLC
//
// 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
//
//     https://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 dap_optional_h
#define dap_optional_h

#include <assert.h>
#include <type_traits>
#include <utility>  // std::move

namespace dap {

// optional holds an 'optional' contained value.
// This is similar to C++17's std::optional.
template <typename T>
class optional {
  template <typename U>
  using IsConvertibleToT =
      typename std::enable_if<std::is_convertible<U, T>::value>::type;

 public:
  using value_type = T;

  // constructors
  inline optional() = default;
  inline optional(const optional& other);
  inline optional(optional&& other);
  template <typename U>
  inline optional(const optional<U>& other);
  template <typename U>
  inline optional(optional<U>&& other);
  template <typename U = value_type, typename = IsConvertibleToT<U>>
  inline optional(U&& value);

  // value() returns the contained value.
  // If the optional does not contain a value, then value() will assert.
  inline T& value();
  inline const T& value() const;

  // value() returns the contained value, or defaultValue if the optional does
  // not contain a value.
  inline const T& value(const T& defaultValue) const;

  // operator bool() returns true if the optional contains a value.
  inline explicit operator bool() const noexcept;

  // has_value() returns true if the optional contains a value.
  inline bool has_value() const;

  // assignment
  inline optional& operator=(const optional& other);
  inline optional& operator=(optional&& other) noexcept;
  template <typename U = T, typename = IsConvertibleToT<U>>
  inline optional& operator=(U&& value);
  template <typename U>
  inline optional& operator=(const optional<U>& other);
  template <typename U>
  inline optional& operator=(optional<U>&& other);

  // value access
  inline const T* operator->() const;
  inline T* operator->();
  inline const T& operator*() const;
  inline T& operator*();

 private:
  T val = {};
  bool set = false;
};

template <typename T>
optional<T>::optional(const optional& other) : val(other.val), set(other.set) {}

template <typename T>
optional<T>::optional(optional&& other)
    : val(std::move(other.val)), set(other.set) {}

template <typename T>
template <typename U>
optional<T>::optional(const optional<U>& other) : set(other.has_value()) {
  if (set) {
    val = static_cast<T>(other.value());
  }
}

template <typename T>
template <typename U>
optional<T>::optional(optional<U>&& other) : set(other.has_value()) {
  if (set) {
    val = static_cast<T>(std::move(other.value()));
  }
}

template <typename T>
template <typename U /*= T*/, typename>
optional<T>::optional(U&& value) : val(std::move(value)), set(true) {}

template <typename T>
T& optional<T>::value() {
  assert(set);
  return val;
}

template <typename T>
const T& optional<T>::value() const {
  assert(set);
  return val;
}

template <typename T>
const T& optional<T>::value(const T& defaultValue) const {
  if (!has_value()) {
    return defaultValue;
  }
  return val;
}

template <typename T>
optional<T>::operator bool() const noexcept {
  return set;
}

template <typename T>
bool optional<T>::has_value() const {
  return set;
}

template <typename T>
optional<T>& optional<T>::operator=(const optional& other) {
  val = other.val;
  set = other.set;
  return *this;
}

template <typename T>
optional<T>& optional<T>::operator=(optional&& other) noexcept {
  val = std::move(other.val);
  set = other.set;
  return *this;
}

template <typename T>
template <typename U /* = T */, typename>
optional<T>& optional<T>::operator=(U&& value) {
  val = std::move(value);
  set = true;
  return *this;
}

template <typename T>
template <typename U>
optional<T>& optional<T>::operator=(const optional<U>& other) {
  val = other.val;
  set = other.set;
  return *this;
}

template <typename T>
template <typename U>
optional<T>& optional<T>::operator=(optional<U>&& other) {
  val = std::move(other.val);
  set = other.set;
  return *this;
}

template <typename T>
const T* optional<T>::operator->() const {
  assert(set);
  return &val;
}

template <typename T>
T* optional<T>::operator->() {
  assert(set);
  return &val;
}

template <typename T>
const T& optional<T>::operator*() const {
  assert(set);
  return val;
}

template <typename T>
T& optional<T>::operator*() {
  assert(set);
  return val;
}

template <class T, class U>
inline bool operator==(const optional<T>& lhs, const optional<U>& rhs) {
  if (!lhs.has_value() && !rhs.has_value()) {
    return true;
  }
  if (!lhs.has_value() || !rhs.has_value()) {
    return false;
  }
  return lhs.value() == rhs.value();
}

template <class T, class U>
inline bool operator!=(const optional<T>& lhs, const optional<U>& rhs) {
  return !(lhs == rhs);
}

template <class T, class U>
inline bool operator<(const optional<T>& lhs, const optional<U>& rhs) {
  if (!rhs.has_value()) {
    return false;
  }
  if (!lhs.has_value()) {
    return true;
  }
  return lhs.value() < rhs.value();
}

template <class T, class U>
inline bool operator<=(const optional<T>& lhs, const optional<U>& rhs) {
  if (!lhs.has_value()) {
    return true;
  }
  if (!rhs.has_value()) {
    return false;
  }
  return lhs.value() <= rhs.value();
}

template <class T, class U>
inline bool operator>(const optional<T>& lhs, const optional<U>& rhs) {
  if (!lhs.has_value()) {
    return false;
  }
  if (!rhs.has_value()) {
    return true;
  }
  return lhs.value() > rhs.value();
}

template <class T, class U>
inline bool operator>=(const optional<T>& lhs, const optional<U>& rhs) {
  if (!rhs.has_value()) {
    return true;
  }
  if (!lhs.has_value()) {
    return false;
  }
  return lhs.value() >= rhs.value();
}

}  // namespace dap

#endif  // dap_optional_h
