#include <windows.h>
#include <SWI-Prolog.h>

#include "pl.h"

Frame::Frame()
{
	m_f = PL_open_foreign_frame();
}

Frame::~Frame()
{
	PL_close_foreign_frame(m_f);
}

void Frame::Close()
{
	PL_close_foreign_frame(m_f);
}

void Frame::Discard()
{
	PL_discard_foreign_frame(m_f);
}

void Frame::Rewind()
{
	PL_rewind_foreign_frame(m_f);
}

Mark::Mark()
{
	PL_mark_string_buffers(&m_m);
}

Mark::~Mark()
{
	PL_release_string_buffers_from_mark(m_m);
}

Query::Query(const module_t ctx, const predicate_t p, const term_t t0)
{
	m_q = PL_open_query(ctx, PL_Q_CATCH_EXCEPTION, p, t0);
}

Query::~Query()
{
	PL_cut_query(m_q);
}

int Query::Cut(std::nothrow_t)
{
	return PL_cut_query(m_q);
}
int Query::Cut()
{
	if (PL_cut_query(m_q)) return 1;
	if (const term_t t = PL_exception(m_q)) throw t;
	return 0;
}

int Query::Close(std::nothrow_t)
{
	return PL_close_query(m_q);
}

int Query::Close()
{
	if (PL_close_query(m_q)) return 1;
	if (const term_t t = PL_exception(m_q)) throw t;
	return 0;
}

int Query::NextSolution(std::nothrow_t)
{
	return PL_next_solution(m_q);
}

int Query::NextSolution()
{
	if (PL_next_solution(m_q)) return 1;
	if (const term_t t = PL_exception(m_q)) throw t;
	return 0;
}

WcharPtr PlString(const term_t t, const int flags)
{
	char* s;
	if (PL_get_chars(t, &s, flags))
		return {WcharPtr::FromNarrow(s)};
	else
		return {};
}