/******************************************************************************
 *    ScriptModule.cpp
 *
 *    This file is part of Public Scripts
 *    Copyright (C) 2005-2009 Tom N Harris <telliamed@whoopdedo.org>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 *****************************************************************************/

#include "ScriptModule.h"

#include <cstring>

#include <lg/scrmanagers.h>
#include <lg/malloc.h>


static int __cdecl NullPrintf(const char*, ...);

IMalloc *g_pMalloc = NULL;
IScriptMan *g_pScriptManager = NULL;
volatile MPrintfProc g_pfnMPrintf = NullPrintf;

static int __cdecl NullPrintf(const char*, ...)
{
	return 0;
}

cScriptModule::~cScriptModule()
{
	if (m_pszName)
		delete[] m_pszName;
}

cScriptModule::cScriptModule()
	    : m_iRef(1), m_pszName(NULL)
{
}

cScriptModule::cScriptModule(const char* pszName)
	    : m_iRef(1), m_pszName(NULL)
{
	SetName(pszName);
}

HRESULT __stdcall cScriptModule::QueryInterface(REFIID riid, void** ppout)
{
	if (riid == IID_IUnknown)
		*ppout = static_cast<IUnknown*>(this);
	else if (riid == IID_IScriptModule)
		*ppout = static_cast<IScriptModule*>(this);
	else
		return E_NOINTERFACE;
	reinterpret_cast<IUnknown*>(*ppout)->AddRef();
	return S_OK;
}

ULONG __stdcall cScriptModule::AddRef(void) 
{
	return ++m_iRef;
}

ULONG __stdcall cScriptModule::Release(void)
{
	// This object is static, so we don't delete it.
	int iRefCnt = --m_iRef;
	if (iRefCnt < 0)
		iRefCnt = m_iRef = 0;
	return iRefCnt;
}

void cScriptModule::SetName(const char* pszName)
{
	if (m_pszName)
		delete[] m_pszName;
	if (pszName)
	{
		m_pszName = new char[::strlen(pszName)+1];
		::strcpy(m_pszName, pszName);
	}
	else
		m_pszName = NULL;
}

const char* __stdcall cScriptModule::GetName(void)
{
	return m_pszName;
}

const sScrClassDesc* cScriptModule::GetScript(unsigned int i)
{
	if (i < sm_ScriptsArraySize)
		return &sm_ScriptsArray[i];
	else
		return NULL;
}

const sScrClassDesc* __stdcall cScriptModule::GetFirstClass(tScrIter* pIterParam)
{
	*reinterpret_cast<unsigned int*>(pIterParam) = 0;
	return GetScript(0);
}

const sScrClassDesc* __stdcall cScriptModule::GetNextClass(tScrIter* pIterParam) 
{
	const sScrClassDesc *pRet;
	register unsigned int index = *reinterpret_cast<unsigned int*>(pIterParam);
	pRet = GetScript(++index);
	*reinterpret_cast<unsigned int*>(pIterParam) = index;
	return pRet;
}

void __stdcall cScriptModule::EndClassIter(tScrIter*)
{
	// Nothing to do here
}


cScriptModule  g_ScriptModule;

/*
static bool IsWinNT(void)
{
	OSVERSIONINFO vi;
	vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	if (! ::GetVersionEx(&vi))
		return false;
	return vi.dwPlatformId == VER_PLATFORM_WIN32_NT;
}
*/

extern "C" 
int __declspec(dllexport) __stdcall 
ScriptModuleInit (const char* pszName, 
                  IScriptMan* pScriptMan,
                  MPrintfProc pfnMPrintf,
                  IMalloc* pMalloc,
                  IScriptModule** pOutInterface)
{
	*pOutInterface = NULL;

	g_pScriptManager = pScriptMan;
#ifdef _DEBUG
	pMalloc->QueryInterface(IID_IDebugMalloc, reinterpret_cast<void**>(&g_pMalloc));
	if (!g_pMalloc)
		g_pMalloc = pMalloc;
#else
	g_pMalloc = pMalloc;
#endif

	if (pfnMPrintf)
		g_pfnMPrintf = pfnMPrintf;

	if (!g_pScriptManager || !g_pMalloc)
		return 0;

	g_ScriptModule.SetName(pszName);
	g_ScriptModule.QueryInterface(IID_IScriptModule, reinterpret_cast<void**>(pOutInterface));

	return 1;
}

extern "C"
BOOL WINAPI 
DllMain (HINSTANCE hDLL, DWORD dwReason, PVOID lpResv)
{
	if (dwReason == DLL_PROCESS_ATTACH)
	{
		::DisableThreadLibraryCalls(hDLL);
		return TRUE;
	}
	return TRUE;
#ifdef __GNUC__
	lpResv = lpResv;
#endif
#ifdef __BORLANDC__
#pragma argsused(hDLL,dwReason)
#endif
}
