/**************************************************************
 * 
 * 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 <vector>
#include <algorithm>
#include <basic/sbx.hxx>
#include <unotools/moduleoptions.hxx>

#include <iderdll.hxx>
#include <iderdll2.hxx>
#include <basobj.hxx>
#include <basidesh.hxx>
#include <objdlg.hxx>
#include <bastypes.hxx>
#include <basdoc.hxx>
#include <basidesh.hrc>

#include <baside2.hxx>
#include <baside3.hxx>
#include <basicmod.hxx>
#include <localizationmgr.hxx>
#include "dlged.hxx"
#include <dlgeddef.hxx>
#include <comphelper/processfactory.hxx>
#ifndef _COM_SUN_STAR_SCRIPT_XLIBRYARYCONTAINER_HPP_
#include <com/sun/star/script/XLibraryContainer.hpp>
#endif
#include <com/sun/star/script/XLibraryContainerPassword.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <xmlscript/xmldlg_imexp.hxx>
#include <rtl/uri.hxx>
#include <osl/process.h>
#include <osl/file.hxx>

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


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

extern "C" {
    SAL_DLLPUBLIC_EXPORT long basicide_handle_basic_error( void* pPtr )
	{
        return BasicIDE::HandleBasicError( (StarBASIC*)pPtr );
    }
}

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

SbMethod* CreateMacro( SbModule* pModule, const String& rMacroName )
{
    BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
    SfxViewFrame* pViewFrame = pIDEShell ? pIDEShell->GetViewFrame() : NULL;
	SfxDispatcher* pDispatcher = pViewFrame ? pViewFrame->GetDispatcher() : NULL;

    if( pDispatcher )
	{
		pDispatcher->Execute( SID_BASICIDE_STOREALLMODULESOURCES );
	}

	if ( pModule->GetMethods()->Find( rMacroName, SbxCLASS_METHOD ) )
		return 0;

	String aMacroName( rMacroName );
	if ( aMacroName.Len() == 0 )
	{
		if ( !pModule->GetMethods()->Count() )
			aMacroName = String( RTL_CONSTASCII_USTRINGPARAM( "Main" ) );
		else
		{
			sal_Bool bValid = sal_False;
			String aStdMacroText( RTL_CONSTASCII_USTRINGPARAM( "Macro" ) );
			//String aStdMacroText( IDEResId( RID_STR_STDMACRONAME ) );
			sal_uInt16 nMacro = 1;
			while ( !bValid )
			{
				aMacroName = aStdMacroText;
				aMacroName += String::CreateFromInt32( nMacro );
				// Pruefen, ob vorhanden...
				bValid = pModule->GetMethods()->Find( aMacroName, SbxCLASS_METHOD ) ? sal_False : sal_True;
				nMacro++;
			}
		}
	}

    ::rtl::OUString aOUSource( pModule->GetSource32() );

	// Nicht zu viele Leerzeilen erzeugen...
    sal_Int32 nSourceLen = aOUSource.getLength();
	if ( nSourceLen > 2 )
	{
        const sal_Unicode* pStr = aOUSource.getStr();
		if ( pStr[ nSourceLen - 1 ]  != LINE_SEP )
			aOUSource += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n\n" ) );
		else if ( pStr[ nSourceLen - 2 ] != LINE_SEP )
			aOUSource += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ) );
		else if ( pStr[ nSourceLen - 3 ] == LINE_SEP )
			aOUSource = aOUSource.copy( 0, nSourceLen-1 );
	}

	::rtl::OUString aSubStr;
	aSubStr = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Sub " ) );
	aSubStr += aMacroName;
	aSubStr += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n\nEnd Sub" ) );

	aOUSource += aSubStr;

    // update module in library
    ScriptDocument aDocument( ScriptDocument::NoDocument );
    SbxObject* pParent = pModule->GetParent();
	StarBASIC* pBasic = PTR_CAST(StarBASIC,pParent);
    DBG_ASSERT(pBasic, "BasicIDE::CreateMacro: No Basic found!");
    if ( pBasic )
	{
		BasicManager* pBasMgr = BasicIDE::FindBasicManager( pBasic );
		DBG_ASSERT(pBasMgr, "BasicIDE::CreateMacro: No BasicManager found!");
		if ( pBasMgr )
		{
            aDocument = ScriptDocument::getDocumentForBasicManager( pBasMgr );
            OSL_ENSURE( aDocument.isValid(), "BasicIDE::CreateMacro: no document for the given BasicManager!" );
            if ( aDocument.isValid() )
            {
        	    String aLibName = pBasic->GetName();
	            String aModName = pModule->GetName();
                OSL_VERIFY( aDocument.updateModule( aLibName, aModName, aOUSource ) );
            }
        }
    }

    SbMethod* pMethod = (SbMethod*)pModule->GetMethods()->Find( aMacroName, SbxCLASS_METHOD );

    if( pDispatcher )
	{
		pDispatcher->Execute( SID_BASICIDE_UPDATEALLMODULESOURCES );
	}

    if ( aDocument.isAlive() )
        BasicIDE::MarkDocumentModified( aDocument );

    return pMethod;
}

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

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

    if ( rDocument.hasDialog( 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;
    }

    BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
    IDEBaseWindow* pWin = pIDEShell ? pIDEShell->FindWindow( rDocument, rLibName, rOldName, BASICIDE_TYPE_DIALOG, sal_False ) : NULL;
    Reference< XNameContainer > xExistingDialog;
    if ( pWin )
        xExistingDialog = ((DialogWindow*)pWin)->GetEditor()->GetDialog();

    if ( xExistingDialog.is() )
        LocalizationMgr::renameStringResourceIDs( rDocument, rLibName, rNewName, xExistingDialog );

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

	if ( pWin )
	{
		// set new name in window
		pWin->SetName( rNewName );

		// update property browser
		((DialogWindow*)pWin)->UpdateBrowser();

		// 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;
}

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

bool RemoveDialog( const ScriptDocument& rDocument, const String& rLibName, const String& rDlgName )
{
    BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
    if ( pIDEShell )
	{
		DialogWindow* pDlgWin = pIDEShell->FindDlgWin( rDocument, rLibName, rDlgName, sal_False );
		if( pDlgWin )
		{
			Reference< container::XNameContainer > xDialogModel = pDlgWin->GetDialog();
			LocalizationMgr::removeResourceForDialog( rDocument, rLibName, rDlgName, xDialogModel );
		}
	}

    return rDocument.removeDialog( rLibName, rDlgName );
}

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

StarBASIC* FindBasic( const SbxVariable* pVar )
{
	const SbxVariable* pSbx = pVar;
	while ( pSbx && !pSbx->ISA( StarBASIC ) )
		pSbx = pSbx->GetParent();

	DBG_ASSERT( !pSbx || pSbx->ISA( StarBASIC ), "Find Basic: Kein Basic!" );
	return (StarBASIC*)pSbx;
}

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

BasicManager* FindBasicManager( StarBASIC* pLib )
{
    ScriptDocuments aDocuments( ScriptDocument::getAllScriptDocuments( ScriptDocument::AllWithApplication ) );
    for (   ScriptDocuments::const_iterator doc = aDocuments.begin();
            doc != aDocuments.end();
            ++doc
        )
    {
        BasicManager* pBasicMgr = doc->getBasicManager();
        OSL_ENSURE( pBasicMgr, "BasicIDE::FindBasicManager: no basic manager for the document!" );
        if ( !pBasicMgr )
            continue;

        Sequence< ::rtl::OUString > aLibNames( doc->getLibraryNames() );
        sal_Int32 nLibCount = aLibNames.getLength();
	    const ::rtl::OUString* pLibNames = aLibNames.getConstArray();

        for ( sal_Int32 i = 0 ; i < nLibCount ; i++ )
	    {
            StarBASIC* pL = pBasicMgr->GetLib( pLibNames[ i ] );
			if ( pL == pLib )
				return pBasicMgr;
        }
	}
	return NULL;
}

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

void MarkDocumentModified( const ScriptDocument& rDocument )
{
	// Muss ja nicht aus einem Document kommen...
    if ( rDocument.isApplication() )
    {
        BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
        if ( pIDEShell )
            pIDEShell->SetAppBasicModified();
    }
    else
    {
        rDocument.setDocumentModified();
    }

    SfxBindings* pBindings = BasicIDE::GetBindingsPtr();
    if ( pBindings )
    {
        pBindings->Invalidate( SID_SIGNATURE );
        pBindings->Invalidate( SID_SAVEDOC );
        pBindings->Update( SID_SAVEDOC );
    }

	// Objectcatalog updaten...
	BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
	ObjectCatalog* pObjCatalog = pIDEShell ? pIDEShell->GetObjectCatalog() : 0;
	if ( pObjCatalog )
		pObjCatalog->UpdateEntries();
}

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

void RunMethod( SbMethod* pMethod )
{
	SbxValues aRes;
	aRes.eType = SbxVOID;
	pMethod->Get( aRes );
}

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

void StopBasic()
{
	StarBASIC::Stop();
	BasicIDEShell* pShell = IDE_DLL()->GetShell();
	if ( pShell )
	{
		IDEWindowTable& rWindows = pShell->GetIDEWindowTable();
		IDEBaseWindow* pWin = rWindows.First();
		while ( pWin )
		{
			// BasicStopped von Hand rufen, da das Stop-Notify ggf. sonst nicht
			// durchkommen kann.
			pWin->BasicStopped();
			pWin = rWindows.Next();
		}
	}
	BasicIDE::BasicStopped();
}

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

void BasicStopped( sal_Bool* pbAppWindowDisabled,
		sal_Bool* pbDispatcherLocked, sal_uInt16* pnWaitCount,
		SfxUInt16Item** ppSWActionCount, SfxUInt16Item** ppSWLockViewCount )
{
	// Nach einem Error oder dem expliziten abbrechen des Basics muessen
	// ggf. einige Locks entfernt werden...

	if ( pbAppWindowDisabled )
		*pbAppWindowDisabled = sal_False;
	if ( pbDispatcherLocked )
		*pbDispatcherLocked = sal_False;
	if ( pnWaitCount )
		*pnWaitCount = 0;
	if ( ppSWActionCount )
		*ppSWActionCount = 0;
	if ( ppSWLockViewCount )
		*ppSWLockViewCount = 0;

	// AppWait ?
	sal_uInt16 nWait = 0;
	BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
	if( pIDEShell )
	{
		while ( pIDEShell->GetViewFrame()->GetWindow().IsWait() )
		{
			pIDEShell->GetViewFrame()->GetWindow().LeaveWait();
			nWait++;
		}
		if ( pnWaitCount )
			*pnWaitCount = nWait;
	}

    /*
    // Interactive = sal_False ?
	if ( SFX_APP()->IsDispatcherLocked() )
	{
		SFX_APP()->LockDispatcher( sal_False );
		if ( pbDispatcherLocked )
			*pbDispatcherLocked = sal_True;
    } */

	Window* pDefParent = Application::GetDefDialogParent();
	if ( pDefParent && !pDefParent->IsEnabled() )
	{
		pDefParent->Enable( sal_True );
		if ( pbAppWindowDisabled )
			*pbAppWindowDisabled = sal_True;
	}

}

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

void InvalidateDebuggerSlots()
{
    SfxBindings* pBindings = BasicIDE::GetBindingsPtr();
    if ( pBindings )
    {
        pBindings->Invalidate( SID_BASICSTOP );
        pBindings->Update( SID_BASICSTOP );
        pBindings->Invalidate( SID_BASICRUN );
        pBindings->Update( SID_BASICRUN );
        pBindings->Invalidate( SID_BASICCOMPILE );
        pBindings->Update( SID_BASICCOMPILE );
        pBindings->Invalidate( SID_BASICSTEPOVER );
        pBindings->Update( SID_BASICSTEPOVER );
        pBindings->Invalidate( SID_BASICSTEPINTO );
        pBindings->Update( SID_BASICSTEPINTO );
        pBindings->Invalidate( SID_BASICSTEPOUT );
        pBindings->Update( SID_BASICSTEPOUT );
        pBindings->Invalidate( SID_BASICIDE_TOGGLEBRKPNT );
        pBindings->Update( SID_BASICIDE_TOGGLEBRKPNT );
        pBindings->Invalidate( SID_BASICIDE_STAT_POS );
        pBindings->Update( SID_BASICIDE_STAT_POS );
    }
}

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

long HandleBasicError( StarBASIC* pBasic )
{
	BasicIDEDLL::Init();
    BasicIDE::BasicStopped();

    // no error output during macro choosing
    if ( IDE_DLL()->GetExtraData()->ChoosingMacro() )
		return 1;
	if ( IDE_DLL()->GetExtraData()->ShellInCriticalSection() )
		return 2;

	long nRet = 0;
	BasicIDEShell* pIDEShell = 0;
	if ( SvtModuleOptions().IsBasicIDE() )
	{
		BasicManager* pBasMgr = BasicIDE::FindBasicManager( pBasic );
		if ( pBasMgr )
		{
            sal_Bool bProtected = sal_False;
            ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) );
            OSL_ENSURE( aDocument.isValid(), "BasicIDE::HandleBasicError: no document for the given BasicManager!" );
            if ( aDocument.isValid() )
            {
                ::rtl::OUString aOULibName( pBasic->GetName() );
                Reference< script::XLibraryContainer > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ) );
                if ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) )
                {
                    Reference< script::XLibraryContainerPassword > xPasswd( xModLibContainer, UNO_QUERY );
                    if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( aOULibName ) && !xPasswd->isLibraryPasswordVerified( aOULibName ) )
                    {
                        bProtected = sal_True;
                    }
                }
            }

            if ( !bProtected )
            {
				pIDEShell = IDE_DLL()->GetShell();
				if ( !pIDEShell )
				{
                    SfxAllItemSet aArgs( SFX_APP()->GetPool() );
                    SfxRequest aRequest( SID_BASICIDE_APPEAR, SFX_CALLMODE_SYNCHRON, aArgs );
                    SFX_APP()->ExecuteSlot( aRequest );
					pIDEShell = IDE_DLL()->GetShell();
				}
            }
        }
	}

	if ( pIDEShell )
		nRet = pIDEShell->CallBasicErrorHdl( pBasic );
	else
        ErrorHandler::HandleError( StarBASIC::GetErrorCode() );

	return nRet;
}

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

SfxBindings* GetBindingsPtr()
{
    SfxBindings* pBindings = NULL;

    SfxViewFrame* pFrame = NULL;
    BasicIDEDLL* pIDEDLL = IDE_DLL();
    if ( pIDEDLL && pIDEDLL->GetShell() )
    {
        pFrame = pIDEDLL->GetShell()->GetViewFrame();
    }
    else
    {
        SfxViewFrame* pView = SfxViewFrame::GetFirst();
        while ( pView )
        {
            SfxObjectShell* pObjShell = pView->GetObjectShell();
            if ( pObjShell && pObjShell->ISA( BasicDocShell ) )
            {
                pFrame = pView;
                break;
            }
            pView = SfxViewFrame::GetNext( *pView );
        }
    }
    if ( pFrame != NULL )
        pBindings = &pFrame->GetBindings();

    return pBindings;
}

} //namespace BasicIDE

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