#include "../../include/dv-sdk/module.h"

#include "../main.hpp"

#include <boost/core/demangle.hpp>

#include <typeinfo>

void dvModuleRegisterType(dvModuleData moduleData, const struct dvType type) {
	auto module = reinterpret_cast<dv::Module *>(moduleData);

	try {
		dv::glLibFuncPtr->registerType(module, type);
	}
	catch (const std::exception &ex) {
		dv::Log(dv::logLevel::ERROR, "dvModuleRegisterType(): '{:s} :: {:s}'.",
			boost::core::demangle(typeid(ex).name()), ex.what());
	}
}

void dvModuleRegisterOutput(dvModuleData moduleData, const char *name, const char *typeName) {
	auto module = reinterpret_cast<dv::Module *>(moduleData);

	try {
		dv::glLibFuncPtr->registerOutput(module, name, typeName);
	}
	catch (const std::exception &ex) {
		dv::Log(dv::logLevel::ERROR, "dvModuleRegisterOutput(): '{:s} :: {:s}'.",
			boost::core::demangle(typeid(ex).name()), ex.what());
	}
}

void dvModuleRegisterInput(dvModuleData moduleData, const char *name, const char *typeName, bool optional) {
	auto module = reinterpret_cast<dv::Module *>(moduleData);

	try {
		dv::glLibFuncPtr->registerInput(module, name, typeName, optional);
	}
	catch (const std::exception &ex) {
		dv::Log(dv::logLevel::ERROR, "dvModuleRegisterInput(): '{:s} :: {:s}'.",
			boost::core::demangle(typeid(ex).name()), ex.what());
	}
}

struct dvTypedObject *dvModuleOutputAllocate(dvModuleData moduleData, const char *name) {
	auto module = reinterpret_cast<dv::Module *>(moduleData);

	try {
		return (dv::glLibFuncPtr->outputAllocate(module, name));
	}
	catch (const std::exception &ex) {
		dv::Log(dv::logLevel::ERROR, "dvModuleOutputAllocate(): '{:s} :: {:s}'.",
			boost::core::demangle(typeid(ex).name()), ex.what());

		return (nullptr);
	}
}

void dvModuleOutputCommit(dvModuleData moduleData, const char *name) {
	auto module = reinterpret_cast<dv::Module *>(moduleData);

	try {
		dv::glLibFuncPtr->outputCommit(module, name);
	}
	catch (const std::exception &ex) {
		dv::Log(dv::logLevel::ERROR, "dvModuleOutputCommit(): '{:s} :: {:s}'.",
			boost::core::demangle(typeid(ex).name()), ex.what());
	}
}

const struct dvTypedObject *dvModuleInputGet(dvModuleData moduleData, const char *name) {
	auto module = reinterpret_cast<dv::Module *>(moduleData);

	try {
		return (dv::glLibFuncPtr->inputGet(module, name));
	}
	catch (const std::exception &ex) {
		dv::Log(dv::logLevel::ERROR, "dvModuleInputGet(): '{:s} :: {:s}'.", boost::core::demangle(typeid(ex).name()),
			ex.what());

		return (nullptr);
	}
}

void dvModuleInputAdvance(dvModuleData moduleData, const char *name) {
	auto module = reinterpret_cast<dv::Module *>(moduleData);

	try {
		dv::glLibFuncPtr->inputAdvance(module, name);
	}
	catch (const std::exception &ex) {
		dv::Log(dv::logLevel::ERROR, "dvModuleInputAdvance(): '{:s} :: {:s}'.",
			boost::core::demangle(typeid(ex).name()), ex.what());
	}
}

void dvModuleInputDismiss(dvModuleData moduleData, const char *name, const struct dvTypedObject *data) {
	auto module = reinterpret_cast<dv::Module *>(moduleData);

	try {
		dv::glLibFuncPtr->inputDismiss(module, name, data);
	}
	catch (const std::exception &ex) {
		dv::Log(dv::logLevel::ERROR, "dvModuleInputDismiss(): '{:s} :: {:s}'.",
			boost::core::demangle(typeid(ex).name()), ex.what());
	}
}

dvConfigNode dvModuleOutputGetInfoNode(dvModuleData moduleData, const char *name) {
	auto module = reinterpret_cast<dv::Module *>(moduleData);

	try {
		return (static_cast<dvConfigNode>(dv::glLibFuncPtr->outputGetInfoNode(module, name)));
	}
	catch (const std::exception &ex) {
		dv::Log(dv::logLevel::ERROR, "dvModuleOutputGetInfoNode(): '{:s} :: {:s}'.",
			boost::core::demangle(typeid(ex).name()), ex.what());

		return (nullptr);
	}
}

dvConfigNodeConst dvModuleInputGetInfoNode(dvModuleData moduleData, const char *name) {
	auto module = reinterpret_cast<dv::Module *>(moduleData);

	try {
		return (static_cast<dvConfigNodeConst>(dv::glLibFuncPtr->inputGetInfoNode(module, name)));
	}
	catch (const std::exception &ex) {
		dv::Log(dv::logLevel::ERROR, "dvModuleInputGetInfoNode(): '{:s} :: {:s}'.",
			boost::core::demangle(typeid(ex).name()), ex.what());

		return (nullptr);
	}
}

bool dvModuleInputIsConnected(dvModuleData moduleData, const char *name) {
	auto module = reinterpret_cast<dv::Module *>(moduleData);

	try {
		return (dv::glLibFuncPtr->inputIsConnected(module, name));
	}
	catch (const std::exception &ex) {
		dv::Log(dv::logLevel::ERROR, "dvModuleInputIsConnected(): '{:s} :: {:s}'.",
			boost::core::demangle(typeid(ex).name()), ex.what());

		return (false);
	}
}
