// SPDX-License-Identifier: Apache-2.0
// Copyright Contributors to the OpenTimelineIO project

#pragma once

/// @file safely_typed_any.h
///
/// This file/interface exists only so that we can package/unpackage
/// types with code compiled in one specific library to avoid the type-aliasing
/// problem that any's are subject to.
///
/// Specifically, if you put the same type T in an any from two different
/// libraries across a shared-library boundary, then the actual typeid the any
/// records depends on the library that actually packaged the any. Ditto when
/// trying to pull it out.
///
/// The solution is to have all the unpacking/packing code for the types you
/// care about be instantiated not in headers, but in source code, within one
/// common library. That's why the seemingly silly code in safely_typed_any.cpp
/// exists.

#include "opentime/rationalTime.h"
#include "opentime/timeRange.h"
#include "opentime/timeTransform.h"
#include "opentimelineio/color.h"
#include "opentimelineio/serializableObject.h"
#include "opentimelineio/version.h"

namespace opentimelineio { namespace OPENTIMELINEIO_VERSION {

/// @name Any Create
///@{

std::any create_safely_typed_any(bool&&);
std::any create_safely_typed_any(int&&);
std::any create_safely_typed_any(int64_t&&);
std::any create_safely_typed_any(uint64_t&&);
std::any create_safely_typed_any(double&&);
std::any create_safely_typed_any(std::string&&);
std::any create_safely_typed_any(RationalTime&&);
std::any create_safely_typed_any(TimeRange&&);
std::any create_safely_typed_any(Color&&);
std::any create_safely_typed_any(TimeTransform&&);
std::any create_safely_typed_any(IMATH_NAMESPACE::V2d&&);
std::any create_safely_typed_any(IMATH_NAMESPACE::Box2d&&);
std::any create_safely_typed_any(AnyVector&&);
std::any create_safely_typed_any(AnyDictionary&&);
std::any create_safely_typed_any(SerializableObject*);

///@}

/// @name Any Casting
///@{

bool                   safely_cast_bool_any(std::any const& a);
int                    safely_cast_int_any(std::any const& a);
int64_t                safely_cast_int64_any(std::any const& a);
uint64_t               safely_cast_uint64_any(std::any const& a);
double                 safely_cast_double_any(std::any const& a);
std::string            safely_cast_string_any(std::any const& a);
RationalTime           safely_cast_rational_time_any(std::any const& a);
TimeRange              safely_cast_time_range_any(std::any const& a);
TimeTransform          safely_cast_time_transform_any(std::any const& a);
Color                  safely_cast_color_any(std::any const& a);
IMATH_NAMESPACE::V2d   safely_cast_point_any(std::any const& a);
IMATH_NAMESPACE::Box2d safely_cast_box_any(std::any const& a);

SerializableObject* safely_cast_retainer_any(std::any const& a);

AnyDictionary safely_cast_any_dictionary_any(std::any const& a);
AnyVector     safely_cast_any_vector_any(std::any const& a);

/// @bug Don't use these unless you know what you're doing...
AnyDictionary& temp_safely_cast_any_dictionary_any(std::any const& a);
AnyVector&     temp_safely_cast_any_vector_any(std::any const& a);

///@}

}} // namespace opentimelineio::OPENTIMELINEIO_VERSION
