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

#include <ide_pch.hxx>

#include "basobj.hxx"
#include "iderdll.hxx"
#include "iderdll2.hxx"
#include "iderid.hxx"
#include "macrodlg.hxx"
#include "moduldlg.hxx"
#include "basidesh.hxx"
#include "basidesh.hrc"
#include "baside2.hxx"
#include "basicmod.hxx"
#include "basdoc.hxx"

#include <com/sun/star/document/XEmbeddedScripts.hpp>
#include <com/sun/star/document/XScriptInvocationContext.hpp>

#include <basic/sbx.hxx>
#include <framework/documentundoguard.hxx>
#include <tools/diagnose_ex.h>
#include <unotools/moduleoptions.hxx>

#include <vector>
#include <algorithm>
#include <memory>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::container;


//----------------------------------------------------------------------------

extern "C" {
    SAL_DLLPUBLIC_EXPORT rtl_uString* basicide_choose_macro( void* pOnlyInDocument_AsXModel, sal_Bool bChooseOnly, rtl_uString* pMacroDesc )
	{
		::rtl::OUString aMacroDesc( pMacroDesc );
        Reference< frame::XModel > aDocument( static_cast< frame::XModel* >( pOnlyInDocument_AsXModel ) );
		::rtl::OUString aScriptURL = BasicIDE::ChooseMacro( aDocument, bChooseOnly, aMacroDesc );
		rtl_uString* pScriptURL = aScriptURL.pData;
        rtl_uString_acquire( pScriptURL );

        return pScriptURL;
	}
    SAL_DLLPUBLIC_EXPORT void basicide_macro_organizer( sal_Int16 nTabId )
    {
        OSL_TRACE("in basicide_macro_organizer");
        BasicIDE::Organize( nTabId );
    }
}

namespace BasicIDE
{
//----------------------------------------------------------------------------

void Organize( sal_Int16 tabId )
{
    BasicIDEDLL::Init();

    BasicEntryDescriptor aDesc;
    BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
    if ( pIDEShell )
    {
        IDEBaseWindow* pCurWin = pIDEShell->GetCurWindow();
        if ( pCurWin )
            aDesc = pCurWin->CreateEntryDescriptor();
    }

	Window* pParent = Application::GetDefDialogParent();
	OrganizeDialog* pDlg = new OrganizeDialog( pParent, tabId, aDesc );
	pDlg->Execute();
	delete pDlg;
}

//----------------------------------------------------------------------------

sal_Bool IsValidSbxName( const String& rName )
{
	for ( sal_uInt16 nChar = 0; nChar < rName.Len(); nChar++ )
	{
		sal_Bool bValid = (	( rName.GetChar(nChar) >= 'A' && rName.GetChar(nChar) <= 'Z' ) ||
						( rName.GetChar(nChar) >= 'a' && rName.GetChar(nChar) <= 'z' ) ||
						( rName.GetChar(nChar) >= '0' && rName.GetChar(nChar) <= '9' && nChar ) ||
						( rName.GetChar(nChar) == '_' ) );
		if ( !bValid )
			return sal_False;
	}
	return sal_True;
}

static sal_Bool StringCompareLessThan( const String& rStr1, const String& rStr2 )
{
    return (rStr1.CompareIgnoreCaseToAscii( rStr2 ) == COMPARE_LESS);
}

//----------------------------------------------------------------------------

Sequence< ::rtl::OUString > GetMergedLibraryNames( const Reference< script::XLibraryContainer >& xModLibContainer, const Reference< script::XLibraryContainer >& xDlgLibContainer )
{
    // create a sorted list of module library names
    ::std::vector<String> aModLibList;
    if ( xModLibContainer.is() )
    {
		Sequence< ::rtl::OUString > aModLibNames = xModLibContainer->getElementNames();
		sal_Int32 nModLibCount = aModLibNames.getLength();
		const ::rtl::OUString* pModLibNames = aModLibNames.getConstArray();
        for ( sal_Int32 i = 0 ; i < nModLibCount ; i++ )
			aModLibList.push_back( pModLibNames[ i ] );
        ::std::sort( aModLibList.begin() , aModLibList.end() , StringCompareLessThan );
    }

    // create a sorted list of dialog library names
	::std::vector<String> aDlgLibList;
    if ( xDlgLibContainer.is() )
    {
		Sequence< ::rtl::OUString > aDlgLibNames = xDlgLibContainer->getElementNames();
		sal_Int32 nDlgLibCount = aDlgLibNames.getLength();
		const ::rtl::OUString* pDlgLibNames = aDlgLibNames.getConstArray();
        for ( sal_Int32 i = 0 ; i < nDlgLibCount ; i++ )
			aDlgLibList.push_back( pDlgLibNames[ i ] );
        ::std::sort( aDlgLibList.begin() , aDlgLibList.end() , StringCompareLessThan );
    }

    // merge both lists
    ::std::vector<String> aLibList( aModLibList.size() + aDlgLibList.size() );
    ::std::merge( aModLibList.begin(), aModLibList.end(), aDlgLibList.begin(), aDlgLibList.end(), aLibList.begin(), StringCompareLessThan );
    ::std::vector<String>::iterator aIterEnd = ::std::unique( aLibList.begin(), aLibList.end() );  // move unique elements to the front
    aLibList.erase( aIterEnd, aLibList.end() ); // remove duplicates

    // copy to sequence
	sal_Int32 nLibCount = aLibList.size();
	Sequence< ::rtl::OUString > aSeqLibNames( nLibCount );
    for ( sal_Int32 i = 0 ; i < nLibCount ; i++ )
        aSeqLibNames.getArray()[ i ] = aLibList[ i ];

    return aSeqLibNames;
}

//----------------------------------------------------------------------------

bool RenameModule( Window* pErrorParent, const ScriptDocument& rDocument, const String& rLibName, const String& rOldName, const String& rNewName )
{
    if ( !rDocument.hasModule( rLibName, rOldName ) )
    {
        OSL_ENSURE( false, "BasicIDE::RenameModule: old module name is invalid!" );
        return false;
    }

    if ( rDocument.hasModule( rLibName, rNewName ) )
    {
        ErrorBox aError( pErrorParent, WB_OK | WB_DEF_OK, String( IDEResId( RID_STR_SBXNAMEALLREADYUSED2 ) ) );
        aError.Execute();
		return false;
    }

	// #i74440
	if ( rNewName.Len() == 0 )
    {
        ErrorBox aError( pErrorParent, WB_OK | WB_DEF_OK, String( IDEResId( RID_STR_BADSBXNAME ) ) );
        aError.Execute();
		return false;
    }

    if ( !rDocument.renameModule( rLibName, rOldName, rNewName ) )
        return false;

	BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
	if ( pIDEShell )
	{
		IDEBaseWindow* pWin = pIDEShell->FindWindow( rDocument, rLibName, rNewName, BASICIDE_TYPE_MODULE, sal_True );
		if ( pWin )
		{
			// set new name in window
            pWin->SetName( rNewName );

            // set new module in module window
            ModulWindow* pModWin = (ModulWindow*)pWin;
            pModWin->SetSbModule( (SbModule*)pModWin->GetBasic()->FindModule( rNewName ) );

			// update tabwriter
			sal_uInt16 nId = (sal_uInt16)(pIDEShell->GetIDEWindowTable()).GetKey( pWin );
			DBG_ASSERT( nId, "No entry in Tabbar!" );
			if ( nId )
			{
				BasicIDETabBar*	pTabBar = (BasicIDETabBar*)pIDEShell->GetTabBar();
				pTabBar->SetPageText( nId, rNewName );
				pTabBar->Sort();
				pTabBar->MakeVisible( pTabBar->GetCurPageId() );
			}
		}
	}
    return true;
}


//----------------------------------------------------------------------------

namespace
{
    struct MacroExecutionData
    {
        ScriptDocument  aDocument;
        SbMethodRef     xMethod;

        MacroExecutionData()
            :aDocument( ScriptDocument::NoDocument )
            ,xMethod( NULL )
        {
        }
    };

    class MacroExecution
    {
    public:
        DECL_STATIC_LINK( MacroExecution, ExecuteMacroEvent, MacroExecutionData* );
    };


    IMPL_STATIC_LINK( MacroExecution, ExecuteMacroEvent, MacroExecutionData*, i_pData )
    {
        (void)pThis;
        ENSURE_OR_RETURN( i_pData, "wrong MacroExecutionData", 0L );
        // take ownership of the data
        ::std::auto_ptr< MacroExecutionData > pData( i_pData );

        DBG_ASSERT( pData->xMethod->GetParent()->GetFlags() & SBX_EXTSEARCH, "Kein EXTSEARCH!" );

        // in case this is a document-local macro, try to protect the document's Undo Manager from
        // flawed scripts
        ::std::auto_ptr< ::framework::DocumentUndoGuard > pUndoGuard;
        if ( pData->aDocument.isDocument() )
            pUndoGuard.reset( new ::framework::DocumentUndoGuard( pData->aDocument.getDocument() ) );

        BasicIDE::RunMethod( pData->xMethod );

        return 1L;
    }
}

//----------------------------------------------------------------------------

::rtl::OUString ChooseMacro( const uno::Reference< frame::XModel >& rxLimitToDocument, sal_Bool bChooseOnly, const ::rtl::OUString& rMacroDesc )
{
	(void)rMacroDesc;

	BasicIDEDLL::Init();

	IDE_DLL()->GetExtraData()->ChoosingMacro() = sal_True;

    String aScriptURL;
    sal_Bool bError = sal_False;
    SbMethod* pMethod = NULL;

    ::std::auto_ptr< MacroChooser > pChooser( new MacroChooser( NULL, sal_True ) );
	if ( bChooseOnly || !SvtModuleOptions().IsBasicIDE() )
        pChooser->SetMode( MACROCHOOSER_CHOOSEONLY );

    if ( !bChooseOnly && rxLimitToDocument.is() )
        // Hack!
        pChooser->SetMode( MACROCHOOSER_RECORDING );

	short nRetValue = pChooser->Execute();

	IDE_DLL()->GetExtraData()->ChoosingMacro() = sal_False;

	switch ( nRetValue )
	{
		case MACRO_OK_RUN:
		{
			pMethod = pChooser->GetMacro();
            if ( !pMethod && pChooser->GetMode() == MACROCHOOSER_RECORDING )
                pMethod = pChooser->CreateMacro();

            if ( !pMethod )
                break;

            SbModule* pModule = pMethod->GetModule();
            ENSURE_OR_BREAK( pModule, "BasicIDE::ChooseMacro: No Module found!" );

            StarBASIC* pBasic = (StarBASIC*)pModule->GetParent();
			ENSURE_OR_BREAK( pBasic, "BasicIDE::ChooseMacro: No Basic found!" );

            BasicManager* pBasMgr = BasicIDE::FindBasicManager( pBasic );
			ENSURE_OR_BREAK( pBasMgr, "BasicIDE::ChooseMacro: No BasicManager found!" );

            // name
            String aName;
			aName += pBasic->GetName();
			aName += '.';
			aName += pModule->GetName();
			aName += '.';
			aName += pMethod->GetName();

            // language
            String aLanguage = String::CreateFromAscii("Basic");

            // location
            String aLocation;
			ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) );
            if ( aDocument.isDocument() )
            {
                // document basic
                aLocation = String::CreateFromAscii("document");

                if ( rxLimitToDocument.is() )
                {
                    uno::Reference< frame::XModel > xLimitToDocument( rxLimitToDocument );

                    uno::Reference< document::XEmbeddedScripts > xScripts( rxLimitToDocument, UNO_QUERY );
                    if ( !xScripts.is() )
                    {   // the document itself does not support embedding scripts
                        uno::Reference< document::XScriptInvocationContext > xContext( rxLimitToDocument, UNO_QUERY );
                        if ( xContext.is() )
                            xScripts = xContext->getScriptContainer();
                        if ( xScripts.is() )
                        {   // but it is able to refer to a document which actually does support this
                            xLimitToDocument.set( xScripts, UNO_QUERY );
                            if ( !xLimitToDocument.is() )
                            {
                                OSL_ENSURE( false, "BasicIDE::ChooseMacro: a script container which is no document!?" );
                                xLimitToDocument = rxLimitToDocument;
                            }
                        }
                    }

                    if ( xLimitToDocument != aDocument.getDocument() )
                    {
                        // error
                        bError = sal_True;
                        ErrorBox( NULL, WB_OK | WB_DEF_OK, String( IDEResId( RID_STR_ERRORCHOOSEMACRO ) ) ).Execute();
                    }
                }
            }
            else
            {
                // application basic
                aLocation = String::CreateFromAscii("application");
            }

            // script URL
            if ( !bError )
            {
                aScriptURL = String::CreateFromAscii("vnd.sun.star.script:");
                aScriptURL += aName;
                aScriptURL += String::CreateFromAscii("?language=");
                aScriptURL += aLanguage;
                aScriptURL += String::CreateFromAscii("&location=");
                aScriptURL += aLocation;
            }

			if ( !rxLimitToDocument.is() )
			{
                MacroExecutionData* pExecData = new MacroExecutionData;
                pExecData->aDocument = aDocument;
                pExecData->xMethod = pMethod;   // keep alive until the event has been processed
				Application::PostUserEvent( STATIC_LINK( NULL, MacroExecution, ExecuteMacroEvent ), pExecData );
			}
		}
		break;
	}

    return aScriptURL;
}

//----------------------------------------------------------------------------

Sequence< ::rtl::OUString > GetMethodNames( const ScriptDocument& rDocument, const String& rLibName, const String& rModName )
	throw(NoSuchElementException )
{
    Sequence< ::rtl::OUString > aSeqMethods;

	// get module
    ::rtl::OUString aOUSource;
    if ( rDocument.getModule( rLibName, rModName, aOUSource ) )
    {
	    SbModuleRef xModule = new SbModule( rModName );
	    xModule->SetSource32( aOUSource );
	    sal_uInt16 nCount = xModule->GetMethods()->Count();
		sal_uInt16 nRealCount = nCount;
	    for ( sal_uInt16 i = 0; i < nCount; i++ )
	    {
		    SbMethod* pMethod = (SbMethod*)xModule->GetMethods()->Get( i );
			if( pMethod->IsHidden() )
				--nRealCount;
	    }
        aSeqMethods.realloc( nRealCount );

		sal_uInt16 iTarget = 0;
	    for ( sal_uInt16 i = 0 ; i < nCount; ++i )
	    {
		    SbMethod* pMethod = (SbMethod*)xModule->GetMethods()->Get( i );
			if( pMethod->IsHidden() )
				continue;
		    DBG_ASSERT( pMethod, "Method not found! (NULL)" );
		    aSeqMethods.getArray()[ iTarget++ ] = pMethod->GetName();
	    }
    }

	return aSeqMethods;
}

//----------------------------------------------------------------------------

sal_Bool HasMethod( const ScriptDocument& rDocument, const String& rLibName, const String& rModName, const String& rMethName )
{
    sal_Bool bHasMethod = sal_False;

    ::rtl::OUString aOUSource;
    if ( rDocument.hasModule( rLibName, rModName ) && rDocument.getModule( rLibName, rModName, aOUSource ) )
    {
        SbModuleRef xModule = new SbModule( rModName );
        xModule->SetSource32( aOUSource );
        SbxArray* pMethods = xModule->GetMethods();
        if ( pMethods )
        {
            SbMethod* pMethod = (SbMethod*)pMethods->Find( rMethName, SbxCLASS_METHOD );
            if ( pMethod && !pMethod->IsHidden() )
                bHasMethod = sal_True;
        }
    }

    return bHasMethod;
}
} //namespace BasicIDE
//----------------------------------------------------------------------------
