/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_extensions.hxx"
#include <stdio.h>
#include <stardiv/uno/repos/implementationregistration.hxx>
#include <stardiv/uno/script/script.hxx>
#include <stardiv/uno/beans/exactname.hxx>

#include <rtl/ustring.hxx>
#include <vos/dynload.hxx>
#include <vos/diagnose.hxx>
#include <usr/services.hxx>
#include <vcl/svapp.hxx>
#include <usr/ustring.hxx>
#include <usr/weak.hxx>
#include <tools/string.hxx>
#include <vos/conditn.hxx>

using namespace rtl;
using namespace vos;
using namespace usr;

#define PCHAR_TO_USTRING(x) StringToOUString(String(x),CHARSET_SYSTEM)
#define USTRING_TO_PCHAR(x) OUStringToString(x , CHARSET_DONTKNOW ).GetCharStr()





/*****
*
* A Test root object !
*
*****/
class MyPythonRoot :
		public XInvokation,
		public OWeakObject
{
public:
	MyPythonRoot() { m_iTestValue = 15; }
	BOOL				queryInterface( Uik aUik, XInterfaceRef & rOut );
	void 				acquire() 						 { OWeakObject::acquire(); }
	void 				release() 						 { OWeakObject::release(); }
	void* 				getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }

public:
    XIntrospectionAccessRef getIntrospection(void) const 		THROWS( (UsrSystemException) )
    			{ return XIntrospectionAccessRef();  }

    UsrAny					invoke(	const UString& FunctionName,
    								const Sequence< UsrAny >& Params,
    								Sequence< INT16 >& OutParamIndex,
    								Sequence< UsrAny >& OutParam)
    															THROWS( (	IllegalArgumentException,
    																		CannotConvertException,
    																		InvocationTargetException,
    																		UsrSystemException) );
    void					setValue(const UString& PropertyName, const UsrAny& Value)
    															THROWS( (	UnknownPropertyException,
    																		CannotConvertException,
    																		InvocationTargetException,
    																		UsrSystemException) );

    UsrAny					getValue(const UString& PropertyName)
    															THROWS( (	UnknownPropertyException,
    																		UsrSystemException) );
    BOOL					hasMethod(const UString& Name) const THROWS( (UsrSystemException) );
    BOOL					hasProperty(const UString& Name) const THROWS( (UsrSystemException) );


	void getTestValueViaInout( int &inout )
		{ inout = m_iTestValue; }

	INT32 getTestValue() const
		{ return m_iTestValue; }

	void setTestValue( INT32 i )
		{ m_iTestValue = i; }

	void printTestValue()
		{ fprintf( stderr, "TestValue : %d\n" , getTestValue() ); }

	void addTestValue( INT32 i )
		{ m_iTestValue += i; }

private:

	INT32 m_iTestValue;
};

BOOL MyPythonRoot::queryInterface( Uik aUik, XInterfaceRef &rOut )
{
	if( aUik == XInvokation::getSmartUik() ) {
		rOut = ( XInvokation * ) this;
	}
	else {
		return OWeakObject::queryInterface( aUik , rOut );
	}
	return TRUE;

}

UsrAny	MyPythonRoot::invoke(	const UString& FunctionName,
    							const Sequence< UsrAny >& Params,
    							Sequence< INT16 >& OutParamIndex,
    							Sequence< UsrAny >& OutParam)
    															THROWS( (	IllegalArgumentException,
    																		CannotConvertException,
    																		InvocationTargetException,
    																		UsrSystemException) )
{
	if( L"printTestValue" == FunctionName ) {
		printTestValue();
	}
	else if( L"addTestValue" == FunctionName ) {
		addTestValue( Params.getConstArray()[0].getINT32() );
	}
	else if( L"getTestValueViaInout" == FunctionName ) {
		int i = Params.getConstArray()[0].getINT32();
		getTestValueViaInout( i );
		OutParam.getArray()[0].setINT32( i );
	}
	else {
		THROW( InvocationTargetException() );
	}

	return UsrAny();
}

void	MyPythonRoot::setValue(const UString& PropertyName, const UsrAny& Value)
    															THROWS( (	UnknownPropertyException,
    																		CannotConvertException,
    																		InvocationTargetException,
    																		UsrSystemException) )
{
	if( L"TestValue" == PropertyName ) {
		setTestValue( Value.getINT32() );
	}
	else {
		THROW( UnknownPropertyException() );
	}
}

UsrAny	MyPythonRoot::getValue(const UString& PropertyName)
    															THROWS( (	UnknownPropertyException,
    																		UsrSystemException) )
{
	UsrAny aRet;

	if( L"TestValue" == PropertyName ) {
		aRet.setINT32( getTestValue() );
	}
	else {
		THROW( UnknownPropertyException() );
	}

	return aRet;
}


BOOL	MyPythonRoot::hasMethod(const UString& Name) const 		THROWS( (UsrSystemException) )
{
	if( L"printTestValue" == Name ) {
		return TRUE;
	}
	else if( L"addTestValue" == Name ) {
		return TRUE;
	}
	else if( L"getTestValueViaInout" == Name ) {
		return TRUE;
	}
	return FALSE;
}


BOOL	MyPythonRoot::hasProperty(const UString& Name) const THROWS( (UsrSystemException) )
{
	if( L"TestValue" == Name ) {
		return TRUE;
	}

	return FALSE;
}


/*****
*
* A test engine listener to check the debug interface
*
*****/
class TestListener :
	public XEngineListener,
	public OWeakObject
{
public:

	TestListener()
	{
		m_pDebuggingRef = 0;
	}


	TestListener( XDebuggingRef *p )
	{
		attach( p  );
	}

	~TestListener()
	{
		if( m_pDebuggingRef ) {
			detach();
		}
	}

	BOOL				queryInterface( Uik aUik, XInterfaceRef & rOut );
	void 				acquire() 						 { OWeakObject::acquire(); }
	void 				release() 						 { OWeakObject::release(); }
	void* 				getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }


	void attach( XDebuggingRef *p )
	{
		m_pDebuggingRef = p;
	}

	void detach( );


	virtual void disposing( const EventObject &o )
	{
		if( m_pDebuggingRef ) {
			detach();
		}
	}
    virtual void interrupt(const InterruptEngineEvent& Evt) THROWS( (UsrSystemException) )
    {
    }

    virtual void running(const EventObject& Evt) THROWS( (UsrSystemException) )
   	{
		(*m_pDebuggingRef)->stop();

   		m_aDebugCondition.set();
    }

    virtual void finished(const FinishEngineEvent& Evt) THROWS( (UsrSystemException) )
    {
   		m_aDebugCondition.set();
    }


	void cmdLine();
protected:

	OCondition m_aDebugCondition;
	XDebuggingRef *m_pDebuggingRef;
};



void TestListener::cmdLine()
{
	// Condition is set by running listener
	m_aDebugCondition.wait();
	m_aDebugCondition.reset();
	(*m_pDebuggingRef)->doContinue();
	m_aDebugCondition.wait();
}

void TestListener::detach()
{
	OSL_ASSERT( m_pDebuggingRef );

   	m_pDebuggingRef = 0;
}

BOOL TestListener::queryInterface( Uik aUik, XInterfaceRef & rOut )
{
	if( aUik == XEngineListener::getSmartUik() )
		rOut = (XEngineListener*)this;
	else
		return OWeakObject::queryInterface( aUik, rOut );
	return TRUE;
}


void checkInvokation( const XInvokationRef &xInvoke )
{
	UsrAny anyList;

	// check exporting an object as an invokation
	OSL_ASSERT( xInvoke->hasProperty( L"list" ) );
	anyList = xInvoke->getValue( L"list" );

	OSL_ASSERT( anyList.getReflection() == XInvokation_getReflection() );
	XInvokationRef *pRef = ( XInvokationRef * ) anyList.get();
	OSL_ASSERT( (*pRef).is() );

	OSL_ASSERT( (*pRef)->hasMethod( L"append"  ) );
	OSL_ASSERT( (*pRef)->hasMethod( L"count" ) );

	Sequence<UsrAny> seq(1);
	UsrAny any( (INT32) 1);
	(seq.getArray())[0] = any;

	any = (*pRef)->invoke( L"count" , seq , Sequence<INT16>(), Sequence<UsrAny>() );
	int nOldSize = any.getINT32();

	any = (*pRef)->invoke( L"append" , seq	, Sequence<INT16>(), Sequence<UsrAny>() );
	any = (*pRef)->invoke( L"count" , seq , Sequence<INT16>(), Sequence<UsrAny>() );

	OSL_ASSERT( nOldSize + 1 == any.getINT32() );
}

// just for testing !
class PythonCodeLibrary :
		public XLibraryAccess,
		public OWeakObject
{

	BOOL				queryInterface( Uik aUik, XInterfaceRef & rOut );
	void 				acquire() 						 { OWeakObject::acquire(); }
	void 				release() 						 { OWeakObject::release(); }
	void* 				getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }


    virtual BOOL isFunction(const UString& FunctionName) 			THROWS( (UsrSystemException) )
  	{
  		return FALSE;
  	}

    virtual BOOL isValidPath(const UString& PathName) 				THROWS( (UsrSystemException) )
    {
    	return FALSE;
    }

    virtual Sequence< UString > getModuleNames(void) 				THROWS( (UsrSystemException) )
    {
    	return Sequence<UString> ();
    }

    virtual UString getModuleSource(const UString& ModulName) 		THROWS( (UsrSystemException) )
    {
    	if( ModulName == L"testmodul" ) {
    		return UString( L"def testmethod():\n"
    						L"	return 42\n");
    	}
    	return UString();
    }

    virtual Sequence< BYTE > getModuleCode(const UString& ModuleName) THROWS( (UsrSystemException) )
    {
    	return Sequence< BYTE > ();
    }

    virtual UString getFunctionSource(const UString& FunctionName) THROWS( (UsrSystemException) )
    {
    	return UString();
    }
    virtual Sequence< BYTE > getFunctionCode(const UString& FunctionName) THROWS( (UsrSystemException) )
    {
    	return Sequence< BYTE > ();
    }
};

BOOL PythonCodeLibrary::queryInterface( Uik aUik, XInterfaceRef & rOut )
{
	if( XLibraryAccess::getSmartUik() == aUik ) {
		rOut = (XLibraryAccess* ) this;
	}
	else {
		return OWeakObject::queryInterface( aUik , rOut );
	}

	return TRUE;
}



/*
 * main.
 */
int __LOADONCALLAPI main (int argc, char **argv)
{
	// necessary startup code
	XMultiServiceFactoryRef xSMgr = createRegistryServiceManager();
	registerUsrServices( xSMgr );
	setProcessServiceManager( xSMgr );

	XInterfaceRef x = xSMgr->createInstance( L"stardiv.uno.repos.ImplementationRegistration" );
	XImplementationRegistrationRef xReg( x, USR_QUERY );
	sal_Char szBuf[1024];

	ORealDynamicLoader::computeModuleName( "pythonengine", szBuf, 1024 );
	UString aDllName( StringToOUString( szBuf, CHARSET_SYSTEM ) );
	xReg->registerImplementation( L"stardiv.loader.SharedLibrary", aDllName, XSimpleRegistryRef() );

	x = xSMgr->createInstance( L"stardiv.script.Python" );
	XEngineRef xEngine( x, USR_QUERY );
	XInvokationRef xInvoke(  x, USR_QUERY );
	XDebuggingRef xDebug( x , USR_QUERY );

	XInterfaceRef rRoot( (XInvokation * )new MyPythonRoot , USR_QUERY );
	xEngine->setRoot( rRoot );


	// execute a simple script
	xEngine->run( 	L"nIntTest = 5\n"
					L"list = [2,3,4]\n" , XInterfaceRef(), Sequence<UsrAny> () );

	/****
	*
	* Xinvokation - Test
	*
	*****/
	// get/set an int !
	{
		OSL_ASSERT( xInvoke->hasProperty( L"nIntTest" ) );
		UsrAny any = xInvoke->getValue( L"nIntTest" );

		OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG );
		OSL_ASSERT( any.getINT32() == 5 );

		// simple test: set an int !
		xInvoke->setValue( L"nIntTest" , UsrAny( (INT32) 10 ) );
		any = xInvoke->getValue( L"nIntTest" );

		OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG );
		OSL_ASSERT( any.getINT32() == 10 );
	}

	//  call a python method !
	{
		xEngine->run( L"def foo():\n"
					  L"	return 'this is foo'\n" , XInterfaceRef() , Sequence<UsrAny> () );
		OSL_ASSERT( xInvoke->hasMethod(	L"foo" ) );
		UsrAny any = xInvoke->invoke(	L"foo" ,
										Sequence<UsrAny>(),
										Sequence<INT16>() ,
										Sequence<UsrAny> () );
		OSL_ASSERT( any.getString() == L"this is foo" );
	}


	// check exception handling !
	{
		try {
			xInvoke->invoke( L"foo" , Sequence<UsrAny>(1) , Sequence<INT16>(), Sequence<UsrAny> () );
			// wrong number of arguments
			OSL_ASSERT( 0 );
		}
		catch ( IllegalArgumentException& e ) {
		}
		catch ( InvocationTargetException& e ) {
		}
		catch ( CannotConvertException& e ) {
			// empty any cannot be converted
		}
	}

	// check InOut-Parameter
	checkInvokation( xInvoke );

	/*******
	*
	* Check Introspection Access
	*
	*******/
	{
		XIntrospectionAccessRef xIntrospection = xInvoke->getIntrospection();
		OSL_ASSERT( xIntrospection.is() );

		// no further test, simply call them
		xIntrospection->getMethods(0);
		xIntrospection->getProperties(0);

		OSL_ASSERT( xIntrospection->getSuppliedMethodConcepts() == 0 );
		OSL_ASSERT( xIntrospection->getSuppliedPropertyConcepts() == 0 );

		Property prop = xIntrospection->getProperty( L"nIntTest" ,0 );
		OSL_ASSERT( prop.Name == L"nIntTest" );
		OSL_ASSERT( prop.Type->getTypeClass() == TypeClass_LONG );

		XIdlMethodRef method = xIntrospection->getMethod( L"foo" , 0 );
		OSL_ASSERT( method->getName() == L"foo" );
	}


	/******
	*
	* Multithreading test
	*
	*******/

	/******
	*
	* XDebuggingTest
	*
	******/
	// stop/doContinue + runAsync listener
	{
		// test hangs, if something is wrong

		TestListener *pListener = new TestListener( &xDebug );
		XEngineListenerRef ref( (XEngineListener * ) pListener , USR_QUERY );

		// single listener check !
		xEngine->runAsync( L"pass\n"
							, XInterfaceRef() , Sequence<UsrAny> () , ref );
		pListener->cmdLine();
	}

	// ListenerAdministration check !
	{
		// test hangs, if something is wrong

		TestListener *pListener = new TestListener( &xDebug );
		XEngineListenerRef ref( (XEngineListener * ) pListener , USR_QUERY );

		// engine listener check !
		xEngine->addEngineListener( ref );
		xEngine->runAsync( L"pass\n"
							, XInterfaceRef() , Sequence<UsrAny> () , XEngineListenerRef() );
		pListener->cmdLine();
		xEngine->removeEngineListener( ref);

	}

	// check the import mechanism
	{
		XLibraryAccessRef xLibrary( ( XLibraryAccess * ) new PythonCodeLibrary , USR_QUERY );
		xEngine->setLibraryAccess( xLibrary );

		xEngine->run( 	L"import testmodul\n"
						L"x = testmodul.testmethod()\n" , XInterfaceRef() , Sequence<UsrAny>() );
		UsrAny any = xInvoke->getValue( L"x" );
		OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG );
		OSL_ASSERT( any.getINT32() == 42 );
	}

	// check other imports
	{
		// Check, if the libraries are available at run time
		xEngine->run(	L"import math\n"
						L"dMathTest = math.exp(0)\n"  , XInterfaceRef() , Sequence<UsrAny> () );

		OSL_ASSERT( xInvoke->hasProperty( L"dMathTest" ) );
		UsrAny any = xInvoke->getValue( L"dMathTest" );

		OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_DOUBLE );
		OSL_ASSERT( any.getDouble() == 1. );
	}

	// Test connection to root object !
	{
		xEngine->run( 	L"x = stardiv.root.TestValue\n"
						L"y = stardiv.inout(5)\n"
						L"stardiv.root.getTestValueViaInout(y)\n"
						L"z = y.value\n" , XInterfaceRef() , Sequence<UsrAny> () );

		UsrAny any = xInvoke->getValue( L"x" );
		OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG );
		OSL_ASSERT( any.getINT32() == 15 );

		any = xInvoke->getValue( L"z" );
		OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG );
		OSL_ASSERT( any.getINT32() == 15 );
	}

	// Test exactName interface
	{
		UsrAny any = xInvoke->getValue( L"__builtins__" );
		OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_INTERFACE );

		XInvokationRef rInv( *((XInterfaceRef *) any.get() ), USR_QUERY );
		OSL_ASSERT( rInv.is() );

		XExactNameRef rName( *((XInterfaceRef*) any.get() ), USR_QUERY );
		OSL_ASSERT( rName.is() );

		UString str = rName->getExactName( L"SYNTAXERROR" );
		OSL_ASSERT( str.len() );
	}


	// Test exactName interface of the engine itself
	{
		XExactNameRef rName( xInvoke , USR_QUERY );
		OSL_ASSERT( rName.is() );
		UString str = rName->getExactName( L"STARDIV" );
		OSL_ASSERT( str.len() );
	}


	return 0;
}

