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

#include <svtools/asynclink.hxx>
#include <vos/mutex.hxx>
#include <tools/debug.hxx>
#include <vcl/timer.hxx>
#include <vcl/svapp.hxx>

//--------------------------------------------------------------------
namespace svtools {

void AsynchronLink::CreateMutex()
{
    if( !_pMutex ) _pMutex = new vos::OMutex;
}

void AsynchronLink::Call( void* pObj, sal_Bool
#ifdef DBG_UTIL
bAllowDoubles
#endif
, sal_Bool bUseTimer )
{
#ifdef DBG_UTIL
	if ( bUseTimer || !_bInCall )
		DBG_WARNING( "Recursives Call. Eher ueber Timer. TLX Fragen" );
#endif
	if( _aLink.IsSet() )
	{
		_pArg = pObj;
		DBG_ASSERT( bAllowDoubles ||
					( !_nEventId && ( !_pTimer || !_pTimer->IsActive() ) ),
					"Schon ein Call unterwegs" );
		if( _nEventId )
		{
			if( _pMutex ) _pMutex->acquire();
			Application::RemoveUserEvent( _nEventId );
			if( _pMutex ) _pMutex->release();
		}
		if( _pTimer )_pTimer->Stop();
		if( bUseTimer )
		{
			if( !_pTimer )
			{
				_pTimer = new Timer;
				_pTimer->SetTimeout( 0 );
				_pTimer->SetTimeoutHdl( STATIC_LINK(
					this, AsynchronLink, HandleCall) );
			}
			_pTimer->Start();
		}
		else
		{
			if( _pMutex ) _pMutex->acquire();
            Application::PostUserEvent( _nEventId, STATIC_LINK( this, AsynchronLink, HandleCall), 0 );
			if( _pMutex ) _pMutex->release();
		}
	}
}

AsynchronLink::~AsynchronLink()
{
	if( _nEventId )
	{
		Application::RemoveUserEvent( _nEventId );
	}
	delete _pTimer;
	if( _pDeleted ) *_pDeleted = sal_True;
	delete _pMutex;
}

IMPL_STATIC_LINK( AsynchronLink, HandleCall, void*, EMPTYARG )
{
	if( pThis->_pMutex ) pThis->_pMutex->acquire();
	pThis->_nEventId = 0;
	if( pThis->_pMutex ) pThis->_pMutex->release();
	pThis->Call_Impl( pThis->_pArg );
	return 0;
}

void AsynchronLink::ForcePendingCall()
{
	ClearPendingCall();
	Call_Impl( _pArg );
}

void AsynchronLink::ClearPendingCall()
{
    if( _pMutex ) _pMutex->acquire();
	if( _nEventId )
	{
		Application::RemoveUserEvent( _nEventId );
		_nEventId = 0;
	}
    if( _pMutex ) _pMutex->release();
	if( _pTimer ) _pTimer->Stop();
}

void AsynchronLink::Call_Impl( void* pArg )
{
	_bInCall = sal_True;
	sal_Bool bDeleted = sal_False;
	_pDeleted = &bDeleted;
	_aLink.Call( pArg );
	if( !bDeleted )
	{
		_bInCall = sal_False;
		_pDeleted = 0;
	}
}

}