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


#define CPPUHELPER_TEST_COMPONENT_IMPL
#include "TestComponent.hxx"


#include <string.h>

#include "osl/thread.h"

#include "cppuhelper/implbase1.hxx"
#include "cppuhelper/implementationentry.hxx"

#include "com/sun/star/lang/XMultiComponentFactory.hpp"
#include "com/sun/star/lang/XServiceInfo.hpp"

#include "com/sun/star/uno/XComponentContext.hpp"


#include "cppu/EnvDcp.hxx"

#include <uno/environment.hxx>

using namespace ::com::sun::star;


#define LOG_LIFECYCLE_TestComponent
#ifdef LOG_LIFECYCLE_TestComponent
#  include <iostream>
#  define LOG_LIFECYCLE_TestComponent_emit(x) x

#else
#  define LOG_LIFECYCLE_TestComponent_emit(x)

#endif


class TestComponent: public cppu::WeakImplHelper1<lang::XServiceInfo>
{
	rtl::OUString m_implName;

public:
	static uno::Reference<uno::XInterface> create(
		uno::Reference<uno::XComponentContext> const & xCtx
    )
	SAL_THROW((uno::Exception));


	static uno::Sequence<rtl::OUString> SAL_CALL getSupportedServiceNames_Static();

	explicit TestComponent(uno::Reference<uno::XComponentContext> const & xCtx);
	virtual ~TestComponent();

	uno::Any SAL_CALL queryInterface(uno::Type const & rType ) throw (::com::sun::star::uno::RuntimeException);
	void SAL_CALL release() throw ();
	void SAL_CALL acquire() throw ();
	
	// lang::XServiceInfo
	virtual rtl::OUString SAL_CALL getImplementationName() throw (uno::RuntimeException);
	virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName)
		throw (uno::RuntimeException);
	virtual uno::Sequence<rtl::OUString> SAL_CALL getSupportedServiceNames() 
		throw (uno::RuntimeException);

protected:
	uno::Reference<uno::XComponentContext> m_xComponentContext;
};


uno::Reference<uno::XInterface> SAL_CALL TestComponent::create(
	uno::Reference<uno::XComponentContext> const & xCtx
)
	SAL_THROW((uno::Exception))
{
	try
	{
		return static_cast<cppu::OWeakObject *>(new TestComponent(xCtx));
	}
	catch (std::bad_alloc &)
	{
		throw uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("std::bad_alloc")),
									 uno::Reference<uno::XInterface>());
	}
}

uno::Sequence<rtl::OUString> SAL_CALL TestComponent::getSupportedServiceNames_Static()
{
	uno::Sequence<rtl::OUString> serviceNames(1);
	serviceNames[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.ServiceInfo"));

	return serviceNames;
}


TestComponent::TestComponent(uno::Reference<uno::XComponentContext> const & xCtx)
	: m_xComponentContext(xCtx)
{
	LOG_LIFECYCLE_TestComponent_emit(fprintf(stderr, "LIFE: %s -> %p\n", "TestComponent::TestComponent()", this));
}

TestComponent::~TestComponent()
{
	LOG_LIFECYCLE_TestComponent_emit(fprintf(stderr, "LIFE: %s -> %p\n", "TestComponent::~TestComponent", this));
}

rtl::OUString SAL_CALL TestComponent::getImplementationName() 
	throw (uno::RuntimeException)
{
	return m_implName;
}

void SAL_CALL TestComponent::acquire() throw () 
{
 	cppu::WeakImplHelper1<lang::XServiceInfo>::acquire(); 
} 

void SAL_CALL TestComponent::release() throw () 
{
	cppu::WeakImplHelper1<lang::XServiceInfo>::release(); 
} 

uno::Any SAL_CALL TestComponent::queryInterface(uno::Type const & rType ) throw (::com::sun::star::uno::RuntimeException)
{
	return cppu::WeakImplHelper1<lang::XServiceInfo>::queryInterface(rType); 
}

sal_Bool SAL_CALL TestComponent::supportsService(rtl::OUString const & ServiceName)
	throw (uno::RuntimeException)
{
	uno::Sequence<rtl::OUString> serviceNames = getSupportedServiceNames_Static();

	for (sal_Int32 n = 0; n < serviceNames.getLength(); ++n)
	{
		if (serviceNames[n] == ServiceName)
			return true;
	}

	return false;
}

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

extern "C" sal_Bool SAL_CALL component_writeInfo(
	void * /*serviceManager*/, 
	void * /*registryKey*/
)
{
	g_envDcp = uno::Environment::getCurrent().getTypeName();

	return true;
}

extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
	char const * pImplName, 
	void       * /*serviceManager*/, 
	void       * /*registryKey*/
)
{
	g_envDcp = uno::Environment::getCurrent().getTypeName();

	uno::Reference< lang::XSingleComponentFactory > xFactory;

    rtl::OUString uTmp(pImplName, rtl_str_getLength(pImplName), RTL_TEXTENCODING_ASCII_US);

    rtl::OUString uImplName(cppu::EnvDcp::getTypeName(uTmp));
	rtl::OUString cmpName(RTL_CONSTASCII_USTRINGPARAM("impl.test.TestComponent"));

	if (uImplName.equals(cmpName))
	{
		xFactory = cppu::createSingleComponentFactory(
			TestComponent::create,
			uImplName,
			TestComponent::getSupportedServiceNames_Static());

		xFactory->acquire();
	}

	return xFactory.get();
}

extern "C" SAL_DLLPUBLIC_EXPORT  void SAL_CALL component_getImplementationEnvironmentExt(
	sal_Char        const ** envTypeName, 
	uno_Environment       ** /*ppEnv*/,
	sal_Char        const  * pImplName,
	uno_Environment        * /*pSrcEnv*/
)
{
	rtl::OString purpose;

    if (pImplName) // this is the purpose for a specified impl
    {
        rtl::OUString uImplName(pImplName, rtl_str_getLength(pImplName), RTL_TEXTENCODING_ASCII_US);
        purpose = rtl::OUStringToOString(cppu::EnvDcp::getPurpose(uImplName), RTL_TEXTENCODING_ASCII_US);
    }

    if (!purpose.getLength()) 
    {
        char * pPurpose = getenv("TestComponent.uno");
        if (pPurpose)
            purpose = rtl::OString(pPurpose);
    }

	if (purpose.getLength() == 0)
		*envTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;

	else
	{
		char buff[256];
		strcpy(buff, CPPU_STRINGIFY(CPPU_ENV));
		strcat(buff, purpose.getStr());

		*envTypeName = strdup(buff);
	}
}
