// Copyright (c) 2013 Jascha Wetzel. All rights reserved.

#include "lib_tfd.h"

namespace tfd
{

const int
    ID_LIBRARY_TURBULENCEFD = 1023830;

static TurbulenceFDLibrary*
    tfd_lib_cache = NULL;

static TurbulenceFDLibrary*
CheckTFDLib(Int32 offset)
{ return (TurbulenceFDLibrary*)CheckLib(ID_LIBRARY_TURBULENCEFD, offset, (C4DLibrary**)&tfd_lib_cache); }

#define LIB_CALL(f,...)\
    do { TurbulenceFDLibrary* lib = CheckTFDLib(LIBOFFSET(TurbulenceFDLibrary, f));\
    if ( lib && lib->f ) lib->f(__VA_ARGS__); } while (0)

#define LIB_CALL_PTR(f,T,...)\
    do { TurbulenceFDLibrary* lib = CheckTFDLib(LIBOFFSET(TurbulenceFDLibrary, f));\
    if ( !lib || !lib->f ) return shared_ptr<T>();\
    return shared_ptr<T>(lib->f(__VA_ARGS__), lib->delete_##T); } while (0)

#define LIB_CALL_RET(f,def,...)\
    do { TurbulenceFDLibrary* lib = CheckTFDLib(LIBOFFSET(TurbulenceFDLibrary, f));\
    if ( !lib || !lib->f ) return def;\
    return lib->f(__VA_ARGS__); } while (0)

void TFDFluidContainer::
get_world_to_voxel(Matrix64& m, Vector64& bbox_neg, Vector64& bbox_pos)
{ LIB_CALL(get_world_to_voxel, this, m, bbox_neg, bbox_pos); }

shared_ptr<Channel> TFDFluidContainer::
get_channel(const String& channel)
{ LIB_CALL_PTR(get_channel, Channel, this, channel); }

float TFDFluidContainer::
sample_channel(shared_ptr<Channel>& channel, const Vector64& p, Interpolation interp)
{ LIB_CALL_RET(sample_channel, 0.f, channel.get(), p, interp); }

shared_ptr<Shader> TFDFluidContainer::
get_shader(const String& shader)
{ LIB_CALL_PTR(get_shader, Shader, this, shader); }

Vector4d32 TFDFluidContainer::
sample_shader(shared_ptr<Shader>& shader, const Vector64& p)
{ LIB_CALL_RET(sample_shader, Vector4d32(0.f), shader.get(), p); }

} // namespace tfd
