/**************************************************************
 *
 * 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 <stdio.h>
#include <osl/mutex.hxx>
#include <cppuhelper/factory.hxx>

#include <com/sun/star/uno/XNamingService.hpp>

#include <com/sun/star/registry/XImplementationRegistration.hpp>

#include <com/sun/star/connection/XConnector.hpp>

#include <com/sun/star/bridge/XUnoUrlResolver.hpp>

#include <com/sun/star/lang/XMain.hpp>
#include <com/sun/star/lang/XComponent.hpp>

#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/io/XInputStream.hpp>

#include <cppuhelper/implbase1.hxx>

using namespace ::rtl;
using namespace ::cppu;
using namespace ::osl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;
using namespace ::com::sun::star::connection;
using namespace ::com::sun::star::bridge;
using namespace ::com::sun::star::io;


namespace remotebridges_officeclient {

class PipeClientMain : public WeakImplHelper1< XMain >
{
public:
	PipeClientMain( const Reference< XMultiServiceFactory > &r ) :
		m_xSMgr( r )
		{}
public:     // Methods


    virtual sal_Int32 SAL_CALL run( const Sequence< OUString >& aArguments )
		throw(RuntimeException);


private: // helper methods
	void testPipe( const Reference < XInterface > & rComponent );
	Reference< XMultiServiceFactory > m_xSMgr;
};

void PipeClientMain::testPipe( const Reference< XInterface > & rxInterface )
{
	// ask for the input stream
	Reference< XInputStream > rInputStream( rxInterface, UNO_QUERY );

	// ask for the output stream
	Reference< XOutputStream > rOutputStream( rxInterface, UNO_QUERY );

	if( rInputStream.is() && rOutputStream.is() )
	{
		printf( "got inputstream and outputstream from remote process\n" );

		sal_Int8 a[] = { 5,4,3,2,1,0 };
		Sequence< sal_Int8 > seq( a , 6 );
		rOutputStream->writeBytes( seq );
		rOutputStream->closeOutput();

		Sequence< sal_Int8> seqRead;
		if( rInputStream->readBytes( seqRead ,3 ) != 3 )
		{
			printf( "error : Couldn't read the expected number of bytes\n" );
			return;
		}

		if( seqRead.getConstArray()[0] != 5 ||
			seqRead.getConstArray()[1] != 4 ||
			seqRead.getConstArray()[2] != 3 )
		{
			printf( "error : The array doesn't contain the expected values\n" );
			return;
		}

		// try to read more bytes than written
		if( rInputStream->readBytes( seqRead , 4 ) != 3 )
		{
			printf( "error : Got an unexpected number of bytes\n" );
			return;
		}

		if( seqRead.getConstArray()[0] != 2 ||
			seqRead.getConstArray()[1] != 1 ||
			seqRead.getConstArray()[2] != 0 )
		{
			printf( "error : The array doesn't contain the expected values\n" );
			return;
		}

		printf( "pipe test worked perfect\n" );
	}
	else
	{
		printf( "Couldn't get inputstream and outputstream\n" );
	}
}


sal_Int32 PipeClientMain::run( const Sequence< OUString > & aArguments ) throw ( RuntimeException )
{
	printf( "Connecting ....\n" );

	if( aArguments.getLength() == 1 )
	{
		try {
			Reference < XInterface > r =
				m_xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.bridge.UnoUrlResolver" ) );
			Reference < XUnoUrlResolver > rResolver( r , UNO_QUERY );

			// connect to the remote process and retrieve the initial object
			r = rResolver->resolve( aArguments.getConstArray()[0] );

			if( r.is() )
			{
				printf( "got the remote initial object\n" );
				testPipe( r );
			}
			else
			{
				printf( "error : didn't get the initial object\n" );
			}
		}
		catch( ConnectionSetupException &e )
		{
			OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
			printf( "%s\n", o.pData->buffer );
			printf( "couldn't access local resource ( possible security resons )\n" );
		}
		catch( NoConnectException &e )
		{
			OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
			printf( "%s\n", o.pData->buffer );
			printf( "no server listening on the resource\n" );
		}
		catch( IllegalArgumentException &e )
		{
			OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
			printf( "%s\n", o.pData->buffer );
			printf( "uno url invalid\n" );
		}
		catch( RuntimeException & e )
		{
			OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
			printf( "%s\n", o.pData->buffer );
			printf( "a remote call was aborted\n" );
		}
	}
	else
	{
		printf( "usage: (uno remoteclient-component --) uno-url\n"
		        "e.g.:  uno:socket,host=localhost,port=2083;urp;MyPipe\n" );
		return 1;
	}
	return 0;
}

Reference< XInterface > SAL_CALL CreateInstance( const Reference< XMultiServiceFactory > &r)
{
	return Reference< XInterface > ( ( OWeakObject * ) new PipeClientMain(r) );
}

Sequence< OUString > getSupportedServiceNames()
{
	static Sequence < OUString > *pNames = 0;
	if( ! pNames )
	{
		MutexGuard guard( Mutex::getGlobalMutex() );
		if( !pNames )
		{
			static Sequence< OUString > seqNames(1);
			seqNames.getArray()[0] = OUString::createFromAscii( "com.sun.star.bridge.example.RemoteClientSample" );
			pNames = &seqNames;
		}
	}
	return *pNames;
}

}

using namespace remotebridges_officeclient;
#define IMPLEMENTATION_NAME "com.sun.star.comp.product.example.RemoteClientSample"


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

//==================================================================================================
// SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo(
// 	void * pServiceManager, void * pRegistryKey )
// {
// 	if (pRegistryKey)
// 	{
// 		try
// 		{
// 			Reference< XRegistryKey > xNewKey(
// 				reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey(
// 					OUString::createFromAscii( "/" IMPLEMENTATION_NAME "/UNO/SERVICES" ) ) );

// 			const Sequence< OUString > & rSNL = getSupportedServiceNames();
// 			const OUString * pArray = rSNL.getConstArray();
// 			for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
// 				xNewKey->createKey( pArray[nPos] );

// 			return sal_True;
// 		}
// 		catch (InvalidRegistryException &)
// 		{
// 			OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
// 		}
// 	}
// 	return sal_False;
// }

//==================================================================================================
SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
	const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
	void * pRet = 0;

	if (pServiceManager && rtl_str_compare( pImplName, IMPLEMENTATION_NAME ) == 0)
	{
		Reference< XSingleServiceFactory > xFactory( createSingleFactory(
			reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
			OUString::createFromAscii( pImplName ),
			CreateInstance, getSupportedServiceNames() ) );

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

	return pRet;
}
}
