/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/


#include "precompiled_unotools.hxx"
#include <XTempFile.hxx>
#include <cppuhelper/factory.hxx>
#include <cppuhelper/typeprovider.hxx>
#include <unotools/tempfile.hxx>
#include <osl/file.hxx>
#include <unotools/configmgr.hxx>
#include <tools/urlobj.hxx>
#include <tools/debug.hxx>

namespace css = com::sun::star;

// copy define from desktop\source\app\appinit.cxx

#define DESKTOP_TEMPNAMEBASE_DIR	"/temp/soffice.tmp"

OTempFileService::OTempFileService(::css::uno::Reference< ::css::uno::XComponentContext > const & context)
: ::cppu::PropertySetMixin< ::css::io::XTempFile >(
    context
    , static_cast< Implements >( IMPLEMENTS_PROPERTY_SET | IMPLEMENTS_FAST_PROPERTY_SET | IMPLEMENTS_PROPERTY_ACCESS )
    , com::sun::star::uno::Sequence< rtl::OUString >() )
, mpStream( NULL )
, mbRemoveFile( sal_True )
, mbInClosed( sal_False )
, mbOutClosed( sal_False )
, mnCachedPos( 0 )
, mbHasCachedPos( sal_False )

{
	mpTempFile = new ::utl::TempFile;
	mpTempFile->EnableKillingFile ( sal_True );
}

OTempFileService::~OTempFileService ()
{
	if ( mpTempFile )
		delete mpTempFile;
}


// XInterface

::css::uno::Any SAL_CALL OTempFileService::queryInterface( ::css::uno::Type const & aType )
throw ( ::css::uno::RuntimeException )
{
	::css::uno::Any aResult( OTempFileBase::queryInterface( aType ) );
	if (!aResult.hasValue())
		aResult = cppu::PropertySetMixin< ::css::io::XTempFile >::queryInterface( aType ) ;
	return aResult;
};
void SAL_CALL OTempFileService::acquire(  )
throw ()
{
	OTempFileBase::acquire();
}
void SAL_CALL OTempFileService::release(  )
throw ()
{
	OTempFileBase::release();
}

//	XTypeProvider

::css::uno::Sequence< ::css::uno::Type > SAL_CALL OTempFileService::getTypes(  )
throw ( ::css::uno::RuntimeException )
{
	static ::cppu::OTypeCollection* pTypeCollection = NULL;
	if ( pTypeCollection == NULL )
	{
		::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ) ;

		if ( pTypeCollection == NULL )
		{
			static ::cppu::OTypeCollection aTypeCollection(
				::getCppuType( ( const ::css::uno::Reference< ::css::beans::XPropertySet >*)NULL )
				,OTempFileBase::getTypes() );
			pTypeCollection = &aTypeCollection;
		}
	}
	return pTypeCollection->getTypes();
};
::css::uno::Sequence< sal_Int8 > SAL_CALL OTempFileService::getImplementationId(  )
throw ( ::css::uno::RuntimeException )
{
	return OTempFileBase::getImplementationId();
}

//	XTempFile

sal_Bool SAL_CALL OTempFileService::getRemoveFile()
throw ( ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );

	if ( !mpTempFile )
	{
		// the stream is already disconnected
		throw ::css::uno::RuntimeException();
		}

	return mbRemoveFile;
};
void SAL_CALL OTempFileService::setRemoveFile( sal_Bool _removefile )
throw ( ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );

	if ( !mpTempFile )
	{
		// the stream is already disconnected
		throw ::css::uno::RuntimeException();
	}

	mbRemoveFile = _removefile;
	mpTempFile->EnableKillingFile( mbRemoveFile );
};
::rtl::OUString SAL_CALL OTempFileService::getUri()
throw ( ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );

	if ( !mpTempFile )
	{
		throw ::css::uno::RuntimeException();
	}

	return ::rtl::OUString( mpTempFile->GetURL() );

};
::rtl::OUString SAL_CALL OTempFileService::getResourceName()
throw ( ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );

	if ( !mpTempFile )
	{
		throw ::css::uno::RuntimeException();
}

	return ::rtl::OUString( mpTempFile->GetFileName() );
};



// XInputStream

sal_Int32 SAL_CALL OTempFileService::readBytes( ::css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
throw (::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );
	if ( mbInClosed )
		throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );

	checkConnected();
	if (nBytesToRead < 0)
		throw ::css::io::BufferSizeExceededException( ::rtl::OUString(), static_cast< ::css::uno::XWeak * >(this));

	aData.realloc(nBytesToRead);

	sal_uInt32 nRead = mpStream->Read(static_cast < void* > ( aData.getArray() ), nBytesToRead);
	checkError();

	if (nRead < static_cast < sal_uInt32 > ( nBytesToRead ) )
		aData.realloc( nRead );

	if ( sal::static_int_cast<sal_uInt32>(nBytesToRead) > nRead )
	{
		// usually that means that the stream was read till the end
		// TODO/LATER: it is better to get rid of this optimization by avoiding using of multiple temporary files ( there should be only one temporary file? )
		mnCachedPos = mpStream->Tell();
		mbHasCachedPos = sal_True;

		mpStream = NULL;
		if ( mpTempFile )
			mpTempFile->CloseStream();
	}

	return nRead;
}
sal_Int32 SAL_CALL OTempFileService::readSomeBytes( ::css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );
	if ( mbInClosed )
		throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );

	checkConnected();
	checkError();

	if (nMaxBytesToRead < 0)
		throw ::css::io::BufferSizeExceededException( ::rtl::OUString(), static_cast < ::css::uno::XWeak * >( this ) );

	if (mpStream->IsEof())
	{
		aData.realloc(0);
		return 0;
	}
	else
		return readBytes(aData, nMaxBytesToRead);
}
void SAL_CALL OTempFileService::skipBytes( sal_Int32 nBytesToSkip )
throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );
	if ( mbInClosed )
		throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );

	checkConnected();
	checkError();
	mpStream->SeekRel(nBytesToSkip);
	checkError();
}
sal_Int32 SAL_CALL OTempFileService::available(  )
throw ( ::css::io::NotConnectedException, ::css::io::IOException, ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );
	if ( mbInClosed )
		throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );

	checkConnected();

	sal_uInt32 nPos = mpStream->Tell();
	checkError();

	mpStream->Seek(STREAM_SEEK_TO_END);
	checkError();

	sal_Int32 nAvailable = (sal_Int32)mpStream->Tell() - nPos;
	mpStream->Seek(nPos);
	checkError();

	return nAvailable;
}
void SAL_CALL OTempFileService::closeInput(  )
throw ( ::css::io::NotConnectedException, ::css::io::IOException, ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );
	if ( mbInClosed )
		throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak  * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );

	mbInClosed = sal_True;

	if ( mbOutClosed )
	{
		// stream will be deleted by TempFile implementation
		mpStream = NULL;

		if ( mpTempFile )
		{
			delete mpTempFile;
			mpTempFile = NULL;
		}
	}
}

// XOutputStream

void SAL_CALL OTempFileService::writeBytes( const ::css::uno::Sequence< sal_Int8 >& aData )
throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );
	if ( mbOutClosed )
		throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );

	checkConnected();
	sal_uInt32 nWritten = mpStream->Write(aData.getConstArray(),aData.getLength());
	checkError();
	if	( nWritten != (sal_uInt32)aData.getLength())
		throw ::css::io::BufferSizeExceededException( ::rtl::OUString(),static_cast < ::css::uno::XWeak * > ( this ) );
}
void SAL_CALL OTempFileService::flush(  )
throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );
	if ( mbOutClosed )
		throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );

	checkConnected();
	mpStream->Flush();
	checkError();
}
void SAL_CALL OTempFileService::closeOutput(  )
throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );
	if ( mbOutClosed )
		throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );

	mbOutClosed = sal_True;

	// TODO/LATER: it is better to get rid of this optimization by avoiding using of multiple temporary files ( there should be only one temporary file? )
	if ( mpStream )
	{
		mnCachedPos = mpStream->Tell();
		mbHasCachedPos = sal_True;

		mpStream = NULL;
		if ( mpTempFile )
			mpTempFile->CloseStream();
	}

	if ( mbInClosed )
	{
		// stream will be deleted by TempFile implementation
		mpStream = NULL;

		if ( mpTempFile )
		{
			delete mpTempFile;
			mpTempFile = NULL;
		}
	}
}


void OTempFileService::checkError () const
{
	if (!mpStream || mpStream->SvStream::GetError () != ERRCODE_NONE )
		throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
}
void OTempFileService::checkConnected ()
{
	if (!mpStream && mpTempFile)
	{
		mpStream = mpTempFile->GetStream( STREAM_STD_READWRITE );
		if ( mpStream && mbHasCachedPos )
		{
			mpStream->Seek( sal::static_int_cast<sal_Size>(mnCachedPos) );
			if ( mpStream->SvStream::GetError () == ERRCODE_NONE )
			{
				mbHasCachedPos = sal_False;
				mnCachedPos = 0;
			}
			else
			{
				mpStream = NULL;
				mpTempFile->CloseStream();
			}
		}
	}

	if (!mpStream)
		throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
}

// XSeekable

void SAL_CALL OTempFileService::seek( sal_Int64 nLocation )
throw ( ::css::lang::IllegalArgumentException, ::css::io::IOException, ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );
	checkConnected();
	if ( nLocation < 0 || nLocation > getLength() )
		throw ::css::lang::IllegalArgumentException();

	mpStream->Seek((sal_uInt32) nLocation );
	checkError();
}
sal_Int64 SAL_CALL OTempFileService::getPosition(  )
throw ( ::css::io::IOException, ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );
	checkConnected();

	sal_uInt32 nPos = mpStream->Tell();
	checkError();
	return (sal_Int64)nPos;
}
sal_Int64 SAL_CALL OTempFileService::getLength(  )
throw ( ::css::io::IOException, ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );
	checkConnected();

	sal_uInt32 nCurrentPos = mpStream->Tell();
	checkError();

	mpStream->Seek(STREAM_SEEK_TO_END);
	sal_uInt32 nEndPos = mpStream->Tell();
	mpStream->Seek(nCurrentPos);

	checkError();

	return (sal_Int64)nEndPos;
}


// XStream

::css::uno::Reference< ::css::io::XInputStream > SAL_CALL OTempFileService::getInputStream()
throw ( ::css::uno::RuntimeException )
	{
	return ::css::uno::Reference< ::css::io::XInputStream >( *this, ::css::uno::UNO_QUERY );
}

::css::uno::Reference< ::css::io::XOutputStream > SAL_CALL OTempFileService::getOutputStream()
throw ( ::css::uno::RuntimeException )
	{
	return ::css::uno::Reference< ::css::io::XOutputStream >( *this, ::css::uno::UNO_QUERY );
	}

// XTruncate

void SAL_CALL OTempFileService::truncate()
throw ( ::css::io::IOException, ::css::uno::RuntimeException )
{
	::osl::MutexGuard aGuard( maMutex );
	checkConnected();
	// SetStreamSize() call does not change the position
	mpStream->Seek( 0 );
	mpStream->SetStreamSize( 0 );
	checkError();
}

// XServiceInfo

::rtl::OUString SAL_CALL OTempFileService::getImplementationName()
throw ( ::css::uno::RuntimeException )
{
	return getImplementationName_Static();
}

sal_Bool SAL_CALL OTempFileService::supportsService( ::rtl::OUString const & rServiceName )
throw ( ::css::uno::RuntimeException )
{
	::css::uno::Sequence< ::rtl::OUString > aServices(getSupportedServiceNames_Static());
	return rServiceName == aServices[0];
}

::css::uno::Sequence < ::rtl::OUString > SAL_CALL OTempFileService::getSupportedServiceNames()
throw ( ::css::uno::RuntimeException )
{
	return getSupportedServiceNames_Static();
}



::rtl::OUString OTempFileService::getImplementationName_Static ()
{
	return ::rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.comp.TempFile" ) );
}
::css::uno::Sequence < ::rtl::OUString > OTempFileService::getSupportedServiceNames_Static()
{
	::css::uno::Sequence < ::rtl::OUString > aNames ( 1 );
	aNames[0] = ::rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) );
	return aNames;
}
::css::uno::Reference < ::css::uno::XInterface >SAL_CALL XTempFile_createInstance(
	css::uno::Reference< ::css::uno::XComponentContext > const & context)
	SAL_THROW( ( css::uno::Exception ) )
{
	return static_cast< ::cppu::OWeakObject * >( new OTempFileService(context) );
}

::css::uno::Reference < ::css::lang::XSingleComponentFactory > OTempFileService::createServiceFactory_Static( ::css::uno::Reference < ::css::lang::XMultiServiceFactory > const & )
{
	return ::cppu::createSingleComponentFactory( XTempFile_createInstance, getImplementationName_Static(), getSupportedServiceNames_Static() );
}

// C functions to implement this as a component

extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment(
    			const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ )
{
	*ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

/**
 * This function is called to get service factories for an implementation.
 * @param pImplName name of implementation
 * @param pServiceManager generic uno interface providing a service manager to instantiate components
 * @param pRegistryKey registry data key to read and write component persistent data
 * @return a component factory (generic uno interface)
 */
extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
{
    void * pRet = 0;
	::css::uno::Reference< ::css::lang::XMultiServiceFactory > xSMgr(
		reinterpret_cast< ::css::lang::XMultiServiceFactory * >( pServiceManager ) );
	::css::uno::Reference< ::css::lang::XSingleComponentFactory > xFactory;

	if (OTempFileService::getImplementationName_Static().compareToAscii( pImplName ) == 0)
		xFactory = OTempFileService::createServiceFactory_Static ( xSMgr );

	if ( xFactory.is() )
	{
		xFactory->acquire();
		pRet = xFactory.get();
	}
    return pRet;
}
