#include "any_segment_iterable.hpp"

#include <optional>
#include <type_traits>
#include <utility>

#include "all_type_variant.hpp"
#include "resolve_type.hpp"
#include "storage/create_iterable_from_segment.hpp"
#include "storage/segment_iterables/any_segment_iterable.hpp"
#include "types.hpp"

namespace hyrise::detail {
template <typename T>
AnySegmentIterable<T> CreateAnySegmentIterable<T>::create(const AbstractSegment& abstract_segment) {
  auto any_segment_iterable = std::optional<AnySegmentIterable<T>>{};

  resolve_segment_type<T>(abstract_segment, [&](const auto& segment) {
    if constexpr (std::is_same_v<std::decay_t<decltype(segment)>, ReferenceSegment>) {
      const auto actual_iterable = create_iterable_from_segment<T, false, EraseReferencedSegmentType::Yes>(segment);
      any_segment_iterable.emplace(erase_type_from_iterable(actual_iterable));
    } else {
      const auto actual_iterable = create_iterable_from_segment<T, false>(segment);
      any_segment_iterable.emplace(erase_type_from_iterable(actual_iterable));
    }
  });

  return std::move(*any_segment_iterable);
}

EXPLICITLY_INSTANTIATE_DATA_TYPES(CreateAnySegmentIterable);
}  // namespace hyrise::detail
