/**************************************************************
 * 
 * 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_basic.hxx"

//#include <stl_queue.h>
#include <osl/mutex.hxx>
#include <comphelper/processfactory.hxx>


#include <com/sun/star/script/XEventAttacher.hpp>
#include <com/sun/star/script/XAllListener.hpp>
#include <com/sun/star/script/XScriptEventsSupplier.hpp>
#include <com/sun/star/script/XScriptEventsAttacher.hpp>
#include <com/sun/star/script/ScriptEventDescriptor.hpp>
#include <com/sun/star/script/XLibraryContainer.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/resource/XStringResourceSupplier.hpp>
#include <com/sun/star/resource/XStringResourceManager.hpp>
#include <com/sun/star/awt/XControlContainer.hpp>
#include <com/sun/star/awt/XControlModel.hpp>
#include <com/sun/star/awt/XControl.hpp>
#include <com/sun/star/awt/XDialog.hpp>
#include <com/sun/star/awt/XWindow.hpp>
#include <com/sun/star/script/provider/XScriptProviderFactory.hpp>

#include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
#include <com/sun/star/script/provider/XScriptProvider.hpp>
#include <com/sun/star/awt/XDialogProvider.hpp>

#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/frame/XDesktop.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <basic/basicmanagerrepository.hxx>
#include <basic/basmgr.hxx>
//==================================================================================================

#include <xmlscript/xmldlg_imexp.hxx>
#include <sbunoobj.hxx>
#include <basic/sbstar.hxx>
#include <basic/sbmeth.hxx>
#include <basic/sbuno.hxx>
#include <runtime.hxx>
#include <sbintern.hxx>


#include <cppuhelper/implbase1.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::script;
using namespace ::com::sun::star::resource;

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::script;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::reflection;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::io;
using namespace ::cppu;
using namespace ::osl;


void SFURL_firing_impl( const ScriptEvent& aScriptEvent, Any* pRet, const Reference< frame::XModel >& xModel )
{
        OSL_TRACE("SFURL_firing_impl() processing script url %s",
            ::rtl::OUStringToOString( aScriptEvent.ScriptCode,
                RTL_TEXTENCODING_ASCII_US ).pData->buffer );
        try
        {
            Reference< provider::XScriptProvider > xScriptProvider;
            if ( xModel.is() )
            {
                Reference< provider::XScriptProviderSupplier > xSupplier( xModel, UNO_QUERY );
                OSL_ENSURE( xSupplier.is(), "SFURL_firing_impl: failed to get script provider supplier" );
                if ( xSupplier.is() )
                    xScriptProvider.set( xSupplier->getScriptProvider() );
            }
            else
            {
                Reference< XComponentContext > xContext;
                Reference< XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY );
                OSL_ASSERT( xProps.is() );
                OSL_VERIFY( xProps->getPropertyValue( ::rtl::OUString::createFromAscii( "DefaultContext" ) ) >>= xContext );
                if ( xContext.is() )
                {
                    Reference< provider::XScriptProviderFactory > xFactory(
                        xContext->getValueByName(
                        ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory" ) ),
                        UNO_QUERY );
                    OSL_ENSURE( xFactory.is(), "SFURL_firing_impl: failed to get master script provider factory" );
                    if ( xFactory.is() )
                    {
                        Any aCtx;
                        aCtx <<= ::rtl::OUString::createFromAscii( "user" );
                        xScriptProvider.set( xFactory->createScriptProvider( aCtx ), UNO_QUERY );
                    }
                }
            }

            if ( !xScriptProvider.is() )
            {
                OSL_TRACE("SFURL_firing_impl() Failed to create msp");
                return;
            }
            Sequence< Any > inArgs( 0 );
            Sequence< Any > outArgs( 0 );
            Sequence< sal_Int16 > outIndex;

            // get Arguments for script
            inArgs = aScriptEvent.Arguments;

            Reference< provider::XScript > xScript = xScriptProvider->getScript( aScriptEvent.ScriptCode );

            if ( !xScript.is() )
            {
                OSL_TRACE("SFURL_firing_impl() Failed to obtain XScript");
                return;
            }

            Any result = xScript->invoke( inArgs, outIndex, outArgs );
            if ( pRet )
            {
                *pRet = result;
            }
        }
        catch ( RuntimeException& re )
        {
            OSL_TRACE("SFURL_firing_impl() Caught RuntimeException reason %s.",
                ::rtl::OUStringToOString( re.Message,
                    RTL_TEXTENCODING_ASCII_US ).pData->buffer );
        }
        catch ( Exception& e )
        {
            OSL_TRACE("SFURL_firing_impl() Caught Exception reason %s.",
                ::rtl::OUStringToOString( e.Message,
                    RTL_TEXTENCODING_ASCII_US ).pData->buffer );
        }

}


class BasicScriptListener_Impl : public WeakImplHelper1< XScriptListener >
{
	StarBASICRef maBasicRef;
        Reference< frame::XModel > m_xModel;

	virtual void firing_impl(const ScriptEvent& aScriptEvent, Any* pRet);

public:
    BasicScriptListener_Impl( StarBASIC* pBasic, const Reference< frame::XModel >& xModel )
		: maBasicRef( pBasic ), m_xModel( xModel ) {}

    // Methods of XAllListener
    virtual void SAL_CALL firing(const ScriptEvent& aScriptEvent)
		throw( RuntimeException );
    virtual Any SAL_CALL approveFiring(const ScriptEvent& aScriptEvent)
		throw( InvocationTargetException, RuntimeException );

    // Methods of XEventListener
    virtual void SAL_CALL disposing(const EventObject& Source)
		throw( RuntimeException );
};

// Methods XAllListener
void BasicScriptListener_Impl::firing( const ScriptEvent& aScriptEvent ) throw ( RuntimeException )
{
	firing_impl( aScriptEvent, NULL );
}

Any BasicScriptListener_Impl::approveFiring( const ScriptEvent& aScriptEvent )
	throw ( InvocationTargetException, RuntimeException )
{
	Any aRetAny;
	firing_impl( aScriptEvent, &aRetAny );
	return aRetAny;
}

// Methods XEventListener
void BasicScriptListener_Impl::disposing(const EventObject& ) throw ( RuntimeException )
{
	// TODO: ???
	//vos::OGuard guard( Application::GetSolarMutex() );
	//xSbxObj.Clear();
}


void BasicScriptListener_Impl::firing_impl( const ScriptEvent& aScriptEvent, Any* pRet )
{
	//Guard< Mutex > aGuard( Mutex::getGlobalMutex() );
	//{
	if( aScriptEvent.ScriptType.compareToAscii( "StarBasic" ) == 0 )
	{
		// Full qualified name?
		String aMacro( aScriptEvent.ScriptCode );
		String aLibName;
        String aLocation;
		if( aMacro.GetTokenCount( '.' ) == 3 )
		{
			sal_uInt16 nLast = 0;
			::rtl::OUString aFullLibName = aMacro.GetToken( 0, '.', nLast );

            sal_Int32 nIndex = aFullLibName.indexOf( (sal_Unicode)':' );
            if (nIndex >= 0)
            {
                aLocation = aFullLibName.copy( 0, nIndex );
                aLibName = aFullLibName.copy( nIndex + 1 );
            }

			String aModul = aMacro.GetToken( 0, '.', nLast );
			aMacro.Erase( 0, nLast );
		}

		SbxObject* p = maBasicRef;
		SbxObject* pParent = p->GetParent();
        SbxObject* pParentParent = pParent ? pParent->GetParent() : NULL;

        StarBASICRef xAppStandardBasic;
        StarBASICRef xDocStandardBasic;
        if( pParentParent )
        {
            // Own basic must be document library
            xAppStandardBasic = (StarBASIC*)pParentParent;
            xDocStandardBasic = (StarBASIC*)pParent;
        }
        else if( pParent )
        {
            String aName = p->GetName();
            if( aName.EqualsAscii("Standard") )
            {
                // Own basic is doc standard lib
                xDocStandardBasic = (StarBASIC*)p;
            }
            xAppStandardBasic = (StarBASIC*)pParent;
        }
        else
        {
            xAppStandardBasic = (StarBASIC*)p;
        }

        sal_Bool bSearchLib = true;
        StarBASICRef xLibSearchBasic;
        if( aLocation.EqualsAscii("application") )
            xLibSearchBasic = xAppStandardBasic;
        else if( aLocation.EqualsAscii("document") )
            xLibSearchBasic = xDocStandardBasic;
        else
            bSearchLib = false;

        SbxVariable* pMethVar = NULL;
        // Be still tolerant and make default search if no search basic exists
        if( bSearchLib && xLibSearchBasic.Is() )
        {
            StarBASICRef xLibBasic;
	        sal_Int16 nCount = xLibSearchBasic->GetObjects()->Count();
	        for( sal_Int16 nObj = -1; nObj < nCount ; nObj++ )
	        {
                StarBASIC* pBasic;
                if( nObj == -1 )
                {
		            pBasic = (StarBASIC*)xLibSearchBasic;
                }
                else
                {
		            SbxVariable* pVar = xLibSearchBasic->GetObjects()->Get( nObj );
		            pBasic = dynamic_cast< StarBASIC* >( pVar);
                }
		        if( pBasic )
                {
                    String aName = pBasic->GetName();
                    if( aName == aLibName )
                    {
                        // Search only in the lib, not automatically in application basic
			            sal_uInt16 nFlags = pBasic->GetFlags();
			            pBasic->ResetFlag( SBX_GBLSEARCH );
		                pMethVar = pBasic->Find( aMacro, SbxCLASS_DONTCARE );
			            pBasic->SetFlags( nFlags );
                        break;
                    }
                }
	        }
        }

        // Default: Be tolerant and search everywhere
		if( (!pMethVar || !dynamic_cast< SbMethod* >(pMethVar)) && maBasicRef.Is() )
			pMethVar = maBasicRef->FindQualified( aMacro, SbxCLASS_DONTCARE );

		SbMethod* pMeth = dynamic_cast< SbMethod* >( pMethVar);
		if( !pMeth )
		    return;

		// Setup parameters
		SbxArrayRef xArray;
		String aTmp;
		sal_Int32 nCnt = aScriptEvent.Arguments.getLength();
		if( nCnt )
		{
			xArray = new SbxArray;
			const Any *pArgs = aScriptEvent.Arguments.getConstArray();
			for( sal_Int32 i = 0; i < nCnt; i++ )
			{
				SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
				unoToSbxValue( (SbxVariable*)xVar, pArgs[i] );
				xArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) );
			}
		}

		// Call method
		SbxVariableRef xValue = pRet ? new SbxVariable : 0;
		if( xArray.Is() )
			pMeth->SetParameters( xArray );
		pMeth->Call( xValue );
		if( pRet )
			*pRet = sbxToUnoValue( xValue );
		pMeth->SetParameters( NULL );
	}
    else // scripting framework script
    {
        //callBasic via scripting framework
        SFURL_firing_impl( aScriptEvent, pRet, m_xModel );
    }
}

Any implFindDialogLibForDialog( const Any& rDlgAny, SbxObject* pBasic )
{
	Any aRetDlgLibAny;

    SbxVariable* pDlgLibContVar = pBasic->Find
		(  String::CreateFromAscii("DialogLibraries"), SbxCLASS_OBJECT );
	if( pDlgLibContVar && dynamic_cast< SbUnoObject* >(pDlgLibContVar) )
	{
		SbUnoObject* pDlgLibContUnoObj = (SbUnoObject*)(SbxBase*)pDlgLibContVar;
		Any aDlgLibContAny = pDlgLibContUnoObj->getUnoAny();

		Reference< XLibraryContainer > xDlgLibContNameAccess( aDlgLibContAny, UNO_QUERY );
        OSL_ENSURE( xDlgLibContNameAccess.is(), "implFindDialogLibForDialog: no lib container for the given dialog!" );
		if( xDlgLibContNameAccess.is() )
		{
			Sequence< ::rtl::OUString > aLibNames = xDlgLibContNameAccess->getElementNames();
			const ::rtl::OUString* pLibNames = aLibNames.getConstArray();
			sal_Int32 nLibNameCount = aLibNames.getLength();

			for( sal_Int32 iLib = 0 ; iLib < nLibNameCount ; iLib++ )
			{
                if ( !xDlgLibContNameAccess->isLibraryLoaded( pLibNames[ iLib ] ) )
                    // if the library isn't loaded, then the dialog cannot originate from this lib
                    continue;

				Any aDlgLibAny = xDlgLibContNameAccess->getByName( pLibNames[ iLib ] );

				Reference< XNameAccess > xDlgLibNameAccess( aDlgLibAny, UNO_QUERY );
                OSL_ENSURE( xDlgLibNameAccess.is(), "implFindDialogLibForDialog: invalid dialog lib!" );
				if( xDlgLibNameAccess.is() )
				{
					Sequence< ::rtl::OUString > aDlgNames = xDlgLibNameAccess->getElementNames();
					const ::rtl::OUString* pDlgNames = aDlgNames.getConstArray();
					sal_Int32 nDlgNameCount = aDlgNames.getLength();

					for( sal_Int32 iDlg = 0 ; iDlg < nDlgNameCount ; iDlg++ )
					{
						Any aDlgAny = xDlgLibNameAccess->getByName( pDlgNames[ iDlg ] );
						if( aDlgAny == rDlgAny )
						{
							aRetDlgLibAny = aDlgLibAny;
							break;
						}
					}
				}
			}
		}
	}

	return aRetDlgLibAny;
}

Any implFindDialogLibForDialogBasic( const Any& aAnyISP, SbxObject* pBasic, StarBASIC*& pFoundBasic )
{
	Any aDlgLibAny;
	// Find dialog library for dialog, direct access is not possible here
    StarBASIC* pStartedBasic = (StarBASIC*)pBasic;
	SbxObject* pParentBasic = pStartedBasic ? pStartedBasic->GetParent() : NULL;
	SbxObject* pParentParentBasic = pParentBasic ? pParentBasic->GetParent() : NULL;

	SbxObject* pSearchBasic1 = NULL;
	SbxObject* pSearchBasic2 = NULL;
	if( pParentParentBasic )
	{
		pSearchBasic1 = pParentBasic;
		pSearchBasic2 = pParentParentBasic;
	}
	else
	{
		pSearchBasic1 = pStartedBasic;
		pSearchBasic2 = pParentBasic;
	}
	if( pSearchBasic1 )
	{
		aDlgLibAny = implFindDialogLibForDialog( aAnyISP, pSearchBasic1 );

		if ( aDlgLibAny.hasValue() )
			pFoundBasic = (StarBASIC*)pSearchBasic1;

		else if( pSearchBasic2 )
		{
			aDlgLibAny = implFindDialogLibForDialog( aAnyISP, pSearchBasic2 );
			if ( aDlgLibAny.hasValue() )
				pFoundBasic = (StarBASIC*)pSearchBasic2;
		}
	}
	return aDlgLibAny;
}

static ::rtl::OUString aDecorationPropName =
	::rtl::OUString::createFromAscii( "Decoration" );
static ::rtl::OUString aTitlePropName =
	::rtl::OUString::createFromAscii( "Title" );

void RTL_Impl_CreateUnoDialog( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
{
	static ::rtl::OUString aResourceResolverPropName = ::rtl::OUString::createFromAscii( "ResourceResolver" );

    (void)pBasic;
    (void)bWrite;

	Reference< XMultiServiceFactory > xMSF( comphelper::getProcessServiceFactory() );
	if( !xMSF.is() )
		return;

	// We need at least 1 parameter
	if ( rPar.Count() < 2 )
	{
		StarBASIC::Error( SbERR_BAD_ARGUMENT );
		return;
    }

	// Get dialog
	SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject();
	if( !(pObj && dynamic_cast< SbUnoObject* >((SbxBase*)pObj)) )
	{
		StarBASIC::Error( SbERR_BAD_ARGUMENT );
		return;
	}
	SbUnoObject* pUnoObj = (SbUnoObject*)(SbxBase*)pObj;
	Any aAnyISP = pUnoObj->getUnoAny();
	TypeClass eType = aAnyISP.getValueType().getTypeClass();

	if( eType != TypeClass_INTERFACE )
	{
		StarBASIC::Error( SbERR_BAD_ARGUMENT );
		return;
	}

	// Create new uno dialog
	Reference< XNameContainer > xDialogModel( xMSF->createInstance
		( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControlDialogModel" ) ) ),
			UNO_QUERY );
	if( !xDialogModel.is() )
		return;

	Reference< XInputStreamProvider > xISP;
	aAnyISP >>= xISP;
	if( !xISP.is() )
		return;

    Reference< XComponentContext > xContext;
    Reference< XPropertySet > xProps( xMSF, UNO_QUERY );
    OSL_ASSERT( xProps.is() );
    OSL_VERIFY( xProps->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultContext")) ) >>= xContext );

	// Import the DialogModel
	Reference< XInputStream > xInput( xISP->createInputStream() );

	// i83963 Force decoration
	uno::Reference< beans::XPropertySet > xDlgModPropSet( xDialogModel, uno::UNO_QUERY );
	if( xDlgModPropSet.is() )
	{
		bool bDecoration = true;
		try
		{
			Any aDecorationAny = xDlgModPropSet->getPropertyValue( aDecorationPropName );
			aDecorationAny >>= bDecoration;
			if( !bDecoration )
			{
				xDlgModPropSet->setPropertyValue( aDecorationPropName, makeAny( true ) );
				xDlgModPropSet->setPropertyValue( aTitlePropName, makeAny( ::rtl::OUString() ) );
			}
		}
		catch( UnknownPropertyException& )
		{}
	}

    Any aDlgLibAny;
	bool bDocDialog = false;
	StarBASIC* pFoundBasic = NULL;
    OSL_TRACE("About to try get a hold of ThisComponent");
    Reference< frame::XModel > xModel = StarBASIC::GetModelFromBasic( pINST->GetBasic() ) ;
	aDlgLibAny = implFindDialogLibForDialogBasic( aAnyISP, pINST->GetBasic(), pFoundBasic );
	// If we found the dialog then it belongs to the Search basic
	if ( !pFoundBasic )
	{
		Reference< frame::XDesktop > xDesktop( xMSF->createInstance
    		( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ) ),
			UNO_QUERY );
			Reference< container::XEnumeration > xModels;
		if ( xDesktop.is() )
	    {
			Reference< container::XEnumerationAccess > xComponents( xDesktop->getComponents(), UNO_QUERY );
			if ( xComponents.is() )
				xModels.set( xComponents->createEnumeration(), UNO_QUERY );
			if ( xModels.is() )
			{
				while ( xModels->hasMoreElements() )
				{
					Reference< frame::XModel > xNextModel( xModels->nextElement(), UNO_QUERY );
					if ( xNextModel.is() )
					{
						BasicManager* pMgr = basic::BasicManagerRepository::getDocumentBasicManager( xNextModel );	
						if ( pMgr )
							aDlgLibAny = implFindDialogLibForDialogBasic( aAnyISP, pMgr->GetLib(0), pFoundBasic );
						if ( aDlgLibAny.hasValue() )
                    	{
							bDocDialog = true;
							xModel = xNextModel;
							break;
                        }
					}
				}
			}
		}
	}
	
    if ( pFoundBasic )
		bDocDialog = pFoundBasic->IsDocBasic();
    Reference< XScriptListener > xScriptListener = new BasicScriptListener_Impl( pINST->GetBasic(), xModel );

	Sequence< Any > aArgs( 4 );
	if( bDocDialog )
	   aArgs[ 0 ] <<= xModel;
    else
	   aArgs[ 0 ] <<= uno::Reference< uno::XInterface >();
	aArgs[ 1 ] <<= xInput;
	aArgs[ 2 ] = aDlgLibAny;
	aArgs[ 3 ] <<= xScriptListener;
	// Create a "living" Dialog
        Reference< XControl > xCntrl;
        try
        {
	    Reference< XDialogProvider >  xDlgProv( xMSF->createInstanceWithArguments( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.scripting.DialogProvider" ) ), aArgs ), UNO_QUERY );
            xCntrl.set( xDlgProv->createDialog( rtl::OUString() ), UNO_QUERY_THROW );
           // Add dialog model to dispose vector
           Reference< XComponent > xDlgComponent( xCntrl->getModel(), UNO_QUERY );
           pINST->getComponentVector().push_back( xDlgComponent );
           // need ThisCompoent from calling script
        }
        // preserve existing bad behaviour, it's possible... but probably
        // illegal to open 2 dialogs ( they ARE modal ) when this happens, sometimes
        // create dialog fails.  So, in this case let's not throw, just leave basic
        // detect the unset object.
        catch( uno::Exception& )
        {
        }

	// Return dialog
	Any aRetVal;
	aRetVal <<= xCntrl;
	SbxVariableRef refVar = rPar.Get(0);
	unoToSbxValue( (SbxVariable*)refVar, aRetVal );
}


//===================================================================

