/*
 * Copyright (C) 2016 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 ART_LIBARTBASE_BASE_TRANSFORM_ARRAY_REF_H_
#define ART_LIBARTBASE_BASE_TRANSFORM_ARRAY_REF_H_

#include <type_traits>

#include "array_ref.h"
#include "transform_iterator.h"

namespace art {

/**
 * @brief An ArrayRef<> wrapper that uses a transformation function for element access.
 */
template <typename BaseType, typename Function>
class TransformArrayRef {
 private:
  using Iter = TransformIterator<typename ArrayRef<BaseType>::iterator, Function>;

  // The Function may take a non-const reference, so const_iterator may not exist.
  using FallbackConstIter = std::iterator<std::random_access_iterator_tag, void, void, void, void>;
  using PreferredConstIter =
      TransformIterator<typename ArrayRef<BaseType>::const_iterator, Function>;
  template <typename F, typename = std::result_of_t<F(const BaseType&)>>
  static PreferredConstIter ConstIterHelper(int&);
  template <typename F>
  static FallbackConstIter ConstIterHelper(const int&);

  using ConstIter = decltype(ConstIterHelper<Function>(*reinterpret_cast<int*>(0)));

 public:
  using value_type = typename Iter::value_type;
  using reference = typename Iter::reference;
  using const_reference = typename ConstIter::reference;
  using pointer = typename Iter::pointer;
  using const_pointer = typename ConstIter::pointer;
  using iterator = Iter;
  using const_iterator =
      std::conditional_t<std::is_same_v<ConstIter, FallbackConstIter>, void, ConstIter>;
  using reverse_iterator = std::reverse_iterator<Iter>;
  using const_reverse_iterator = std::conditional_t<std::is_same_v<ConstIter, FallbackConstIter>,
                                                    void,
                                                    std::reverse_iterator<ConstIter>>;
  using difference_type = typename ArrayRef<BaseType>::difference_type;
  using size_type = typename ArrayRef<BaseType>::size_type;

  // Constructors.

  TransformArrayRef(const TransformArrayRef& other) = default;

  template <typename OtherBT>
  TransformArrayRef(const ArrayRef<OtherBT>& base, Function fn)
      : data_(base, fn) { }

  template <typename OtherBT,
            typename = std::enable_if_t<std::is_same_v<BaseType, const OtherBT>>>
  TransformArrayRef(const TransformArrayRef<OtherBT, Function>& other)
      : TransformArrayRef(other.base(), other.GetFunction()) { }

  // Assignment operators.

  TransformArrayRef& operator=(const TransformArrayRef& other) = default;

  template <typename OtherBT,
            typename = std::enable_if_t<std::is_same_v<BaseType, const OtherBT>>>
  TransformArrayRef& operator=(const TransformArrayRef<OtherBT, Function>& other) {
    return *this = TransformArrayRef(other.base(), other.GetFunction());
  }

  // Destructor.
  ~TransformArrayRef() = default;

  // Iterators.
  iterator begin() { return MakeIterator(base().begin()); }
  const_iterator begin() const { return MakeIterator(base().cbegin()); }
  const_iterator cbegin() const { return MakeIterator(base().cbegin()); }
  iterator end() { return MakeIterator(base().end()); }
  const_iterator end() const { return MakeIterator(base().cend()); }
  const_iterator cend() const { return MakeIterator(base().cend()); }
  reverse_iterator rbegin() { return reverse_iterator(end()); }
  const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
  const_reverse_iterator crbegin() const { return const_reverse_iterator(cend()); }
  reverse_iterator rend() { return reverse_iterator(begin()); }
  const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
  const_reverse_iterator crend() const { return const_reverse_iterator(cbegin()); }

  // Size.
  size_type size() const { return base().size(); }
  bool empty() const { return base().empty(); }

  // Element access. NOTE: Not providing data().

  reference operator[](size_type n) { return GetFunction()(base()[n]); }
  const_reference operator[](size_type n) const { return GetFunction()(base()[n]); }

  reference front() { return GetFunction()(base().front()); }
  const_reference front() const { return GetFunction()(base().front()); }

  reference back() { return GetFunction()(base().back()); }
  const_reference back() const { return GetFunction()(base().back()); }

  TransformArrayRef SubArray(size_type pos) {
    return TransformArrayRef(base().subarray(pos), GetFunction());
  }
  TransformArrayRef SubArray(size_type pos) const {
    return TransformArrayRef(base().subarray(pos), GetFunction());
  }
  TransformArrayRef SubArray(size_type pos, size_type length) const {
    return TransformArrayRef(base().subarray(pos, length), GetFunction());
  }

  // Retrieve the base ArrayRef<>.
  ArrayRef<BaseType> base() {
    return data_.base_;
  }
  ArrayRef<const BaseType> base() const {
    return ArrayRef<const BaseType>(data_.base_);
  }

 private:
  // Allow EBO for state-less Function.
  struct Data : Function {
   public:
    Data(ArrayRef<BaseType> base, Function fn) : Function(fn), base_(base) { }

    ArrayRef<BaseType> base_;
  };

  const Function& GetFunction() const {
    return static_cast<const Function&>(data_);
  }

  template <typename BaseIterator>
  auto MakeIterator(BaseIterator base) const {
    return MakeTransformIterator(base, GetFunction());
  }

  Data data_;

  template <typename OtherBT, typename OtherFunction>
  friend class TransformArrayRef;
};

template <typename BaseType, typename Function>
bool operator==(const TransformArrayRef<BaseType, Function>& lhs,
                const TransformArrayRef<BaseType, Function>& rhs) {
  return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
}

template <typename BaseType, typename Function>
bool operator!=(const TransformArrayRef<BaseType, Function>& lhs,
                const TransformArrayRef<BaseType, Function>& rhs) {
  return !(lhs == rhs);
}

template <typename ValueType, typename Function>
TransformArrayRef<ValueType, Function> MakeTransformArrayRef(
    ArrayRef<ValueType> container, Function f) {
  return TransformArrayRef<ValueType, Function>(container, f);
}

template <typename Container, typename Function>
TransformArrayRef<typename Container::value_type, Function> MakeTransformArrayRef(
    Container& container, Function f) {
  return TransformArrayRef<typename Container::value_type, Function>(
      ArrayRef<typename Container::value_type>(container.data(), container.size()), f);
}

template <typename Container, typename Function>
TransformArrayRef<const typename Container::value_type, Function> MakeTransformArrayRef(
    const Container& container, Function f) {
  return TransformArrayRef<const typename Container::value_type, Function>(
      ArrayRef<const typename Container::value_type>(container.data(), container.size()), f);
}

}  // namespace art

#endif  // ART_LIBARTBASE_BASE_TRANSFORM_ARRAY_REF_H_
