/**************************************************************
 *
 * 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_stoc.hxx"
#include <osl/diagnose.h>
#include <osl/mutex.hxx>
#include <uno/dispatcher.h>
#include <uno/mapping.hxx>
#include <cppuhelper/factory.hxx>
#include <cppuhelper/compbase4.hxx>
#include <cppuhelper/implbase2.hxx>
#include <cppuhelper/typeprovider.hxx>

#include <cppuhelper/weakref.hxx>

#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XTypeProvider.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/registry/XSimpleRegistry.hpp>
#include <com/sun/star/registry/XRegistryKey.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
#include "com/sun/star/uno/RuntimeException.hpp"

#include "registry/reader.hxx"
#include "registry/version.h"
#include "base.hxx"
#include "rdbtdp_tdenumeration.hxx"
#include "structtypedescription.hxx"

#define SERVICENAME "com.sun.star.reflection.TypeDescriptionProvider"
#define IMPLNAME	"com.sun.star.comp.stoc.RegistryTypeDescriptionProvider"

using namespace com::sun::star;
using namespace com::sun::star::beans;
using namespace com::sun::star::registry;

extern rtl_StandardModuleCount g_moduleCount;

namespace stoc_bootstrap
{
uno::Sequence< OUString > rdbtdp_getSupportedServiceNames()
{
	static Sequence < OUString > *pNames = 0;
	if( ! pNames )
	{
		MutexGuard guard( Mutex::getGlobalMutex() );
		if( !pNames )
		{
			static Sequence< OUString > seqNames(1);
			seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME));
			pNames = &seqNames;
		}
	}
	return *pNames;
}

OUString rdbtdp_getImplementationName()
{
	static OUString *pImplName = 0;
	if( ! pImplName )
	{
		MutexGuard guard( Mutex::getGlobalMutex() );
		if( ! pImplName )
		{
			static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) );
			pImplName = &implName;
		}
	}
	return *pImplName;
}
}

namespace stoc_rdbtdp
{
struct MutexHolder
{
	Mutex _aComponentMutex;
};
//==================================================================================================
class ProviderImpl
	: public MutexHolder
    , public WeakComponentImplHelper4< XServiceInfo,
                                       XHierarchicalNameAccess,
                                       XTypeDescriptionEnumerationAccess,
                                       XInitialization >
{
    // XHierarchicalNameAccess + XTypeDescriptionEnumerationAccess wrapper
    // first asking the tdmgr instance, then looking up locally
    class TypeDescriptionManagerWrapper
        : public ::cppu::WeakImplHelper2<
            container::XHierarchicalNameAccess,
            reflection::XTypeDescriptionEnumerationAccess>
    {
        com::sun::star::uno::Reference<container::XHierarchicalNameAccess>
        m_xTDMgr;
        com::sun::star::uno::Reference<container::XHierarchicalNameAccess>
        m_xThisProvider;
    public:
        TypeDescriptionManagerWrapper( ProviderImpl * pProvider )
            : m_xTDMgr( pProvider->_xContext->getValueByName(
                            OUString( RTL_CONSTASCII_USTRINGPARAM(
                                          "/singletons/com.sun.star.reflection."
                                          "theTypeDescriptionManager") ) ),
                        UNO_QUERY_THROW ),
              m_xThisProvider( pProvider )
            {}
        // XHierarchicalNameAccess
        virtual Any SAL_CALL getByHierarchicalName( OUString const & name )
            throw (container::NoSuchElementException, RuntimeException);
        virtual sal_Bool SAL_CALL hasByHierarchicalName( OUString const & name )
            throw (RuntimeException);

        // XTypeDescriptionEnumerationAccess
        virtual uno::Reference<
            reflection::XTypeDescriptionEnumeration > SAL_CALL
        createTypeDescriptionEnumeration(
            const ::rtl::OUString& moduleName,
            const uno::Sequence< uno::TypeClass >& types,
            reflection::TypeDescriptionSearchDepth depth )
                throw ( reflection::NoSuchTypeNameException,
                        reflection::InvalidTypeNameException,
                        uno::RuntimeException );
    };
    friend class TypeDescriptionManagerWrapper;

    com::sun::star::uno::Reference< XComponentContext >              _xContext;
    com::sun::star::uno::WeakReference<XHierarchicalNameAccess> _xTDMgr;
    com::sun::star::uno::Reference< XHierarchicalNameAccess > getTDMgr() SAL_THROW( () );

	RegistryKeyList                             _aBaseKeys;

protected:
    virtual void SAL_CALL disposing();

public:
    ProviderImpl( const com::sun::star::uno::Reference< XComponentContext > & xContext );
	virtual ~ProviderImpl();

    // XInitialization
    virtual void SAL_CALL initialize( const Sequence< Any > & args ) throw (Exception, RuntimeException);

	// XServiceInfo
	virtual OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException);
	virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw(::com::sun::star::uno::RuntimeException);
	virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException);

	// XHierarchicalNameAccess
	Any getByHierarchicalNameImpl( const OUString & rName );

	virtual Any SAL_CALL getByHierarchicalName( const OUString & rName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
	virtual sal_Bool SAL_CALL hasByHierarchicalName( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException);

    // XTypeDescriptionEnumerationAccess
    virtual ::com::sun::star::uno::Reference<
        ::com::sun::star::reflection::XTypeDescriptionEnumeration > SAL_CALL
    createTypeDescriptionEnumeration(
        const ::rtl::OUString& moduleName,
        const ::com::sun::star::uno::Sequence<
            ::com::sun::star::uno::TypeClass >& types,
        ::com::sun::star::reflection::TypeDescriptionSearchDepth depth )
            throw ( ::com::sun::star::reflection::NoSuchTypeNameException,
                    ::com::sun::star::reflection::InvalidTypeNameException,
                    ::com::sun::star::uno::RuntimeException );
};
//__________________________________________________________________________________________________
ProviderImpl::ProviderImpl( const com::sun::star::uno::Reference< XComponentContext > & xContext )
    : WeakComponentImplHelper4<
        XServiceInfo, XHierarchicalNameAccess,
        XTypeDescriptionEnumerationAccess, XInitialization >( _aComponentMutex )
	, _xContext( xContext )
{
	g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
}
//__________________________________________________________________________________________________
ProviderImpl::~ProviderImpl()
{
	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
}

//______________________________________________________________________________
Any ProviderImpl::TypeDescriptionManagerWrapper::getByHierarchicalName(
    OUString const & name ) throw (container::NoSuchElementException,
                                   RuntimeException)
{
    try
    {
        // first try tdmgr:
		return m_xTDMgr->getByHierarchicalName( name );
    }
    catch (container::NoSuchElementException &)
    {
        // then lookup locally:
		return m_xThisProvider->getByHierarchicalName( name );
    }
}

//______________________________________________________________________________
sal_Bool ProviderImpl::TypeDescriptionManagerWrapper::hasByHierarchicalName(
    OUString const & name ) throw (RuntimeException)
{
	return m_xTDMgr->hasByHierarchicalName( name ) || m_xThisProvider->hasByHierarchicalName( name );
}

//______________________________________________________________________________
uno::Reference< reflection::XTypeDescriptionEnumeration > SAL_CALL
ProviderImpl::TypeDescriptionManagerWrapper::createTypeDescriptionEnumeration(
        const ::rtl::OUString& moduleName,
        const uno::Sequence< uno::TypeClass >& types,
        reflection::TypeDescriptionSearchDepth depth )
    throw ( reflection::NoSuchTypeNameException,
            reflection::InvalidTypeNameException,
            uno::RuntimeException )
{
    try
    {
        // first try tdmgr:
        uno::Reference< reflection::XTypeDescriptionEnumerationAccess > xTDEA(
            m_xTDMgr, uno::UNO_QUERY_THROW );
        return
            xTDEA->createTypeDescriptionEnumeration( moduleName, types, depth );
    }
    catch (reflection::NoSuchTypeNameException &)
    {
        // then lookup locally:
        uno::Reference< reflection::XTypeDescriptionEnumerationAccess > xTDEA(
            m_xThisProvider, uno::UNO_QUERY_THROW );
        return
            xTDEA->createTypeDescriptionEnumeration( moduleName, types, depth );
    }
}

//__________________________________________________________________________________________________
com::sun::star::uno::Reference< XHierarchicalNameAccess > ProviderImpl::getTDMgr()
    SAL_THROW( () )
{
    // harden weak reference:
    com::sun::star::uno::Reference<container::XHierarchicalNameAccess> xTDMgr(
        _xTDMgr );
    if (! xTDMgr.is())
    {
        xTDMgr.set( new TypeDescriptionManagerWrapper(this) );
        {
        MutexGuard guard( _aComponentMutex );
        _xTDMgr = xTDMgr;
        }
    }
    return xTDMgr;
}

//__________________________________________________________________________________________________
void ProviderImpl::disposing()
{
	_xContext.clear();

	for ( RegistryKeyList::const_iterator iPos( _aBaseKeys.begin() );
		  iPos != _aBaseKeys.end(); ++iPos )
	{
		(*iPos)->closeKey();
	}
	_aBaseKeys.clear();
}

// XInitialization
//__________________________________________________________________________________________________
void ProviderImpl::initialize(
    const Sequence< Any > & args )
    throw (Exception, RuntimeException)
{
    // registries to read from
    Any const * pRegistries = args.getConstArray();
    for ( sal_Int32 nPos = 0; nPos < args.getLength(); ++nPos )
    {
        com::sun::star::uno::Reference< XSimpleRegistry > xRegistry( pRegistries[ nPos ], UNO_QUERY );
        if (xRegistry.is() && xRegistry->isValid())
        {
            com::sun::star::uno::Reference< XRegistryKey > xKey( xRegistry->getRootKey()->openKey(
                OUString( RTL_CONSTASCII_USTRINGPARAM("/UCR") ) ) );
            if (xKey.is() && xKey->isValid())
            {
                _aBaseKeys.push_back( xKey );
            }
        }
    }
}

// XServiceInfo
//__________________________________________________________________________________________________
OUString ProviderImpl::getImplementationName()
	throw(::com::sun::star::uno::RuntimeException)
{
	return stoc_bootstrap::rdbtdp_getImplementationName();
}
//__________________________________________________________________________________________________
sal_Bool ProviderImpl::supportsService( const OUString & rServiceName )
	throw(::com::sun::star::uno::RuntimeException)
{
	const Sequence< OUString > & rSNL = getSupportedServiceNames();
	const OUString * pArray = rSNL.getConstArray();
	for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
	{
		if (pArray[nPos] == rServiceName)
			return sal_True;
	}
	return sal_False;
}
//__________________________________________________________________________________________________
Sequence< OUString > ProviderImpl::getSupportedServiceNames()
	throw(::com::sun::star::uno::RuntimeException)
{
	return stoc_bootstrap::rdbtdp_getSupportedServiceNames();
}

// XHierarchicalNameAccess
//__________________________________________________________________________________________________
Any ProviderImpl::getByHierarchicalNameImpl( const OUString & rName )
{
	Any aRet;

    // read from registry
    OUString aKey( rName.replace( '.', '/' ) );
    for ( RegistryKeyList::const_iterator iPos( _aBaseKeys.begin() );
          !aRet.hasValue() && iPos != _aBaseKeys.end(); ++iPos )
    {
        try
        {
            com::sun::star::uno::Reference< XRegistryKey > xBaseKey( *iPos );
            com::sun::star::uno::Reference< XRegistryKey > xKey( xBaseKey->openKey( aKey ) );
            if (xKey.is())
            {
                // closes key in it's dtor (which is
                // called even in case of exceptions).
                RegistryKeyCloser aCloser( xKey );

                if ( xKey->isValid() )
                {
                    if (xKey->getValueType() == RegistryValueType_BINARY)
                    {
                        Sequence< sal_Int8 > aBytes( xKey->getBinaryValue() );
                        com::sun::star::uno::Reference< XTypeDescription > xTD(
                            createTypeDescription( aBytes,
                                                   getTDMgr(),
                                                   true ) );
                        if ( xTD.is() )
                            aRet <<= xTD;
                    }
                }
            }
            else // might be a constant
            {
                sal_Int32 nIndex = aKey.lastIndexOf( '/' );
                if (nIndex > 0)
                {
                    // open module
                    com::sun::star::uno::Reference< XRegistryKey > xKey2( xBaseKey->openKey( aKey.copy( 0, nIndex ) ) );
                    if (xKey2.is())
                    {
                        // closes key in it's dtor (which is
                        // called even in case of exceptions).
                        RegistryKeyCloser aCloser( xKey2 );

                        if ( xKey2->isValid() )
                        {
                            if (xKey2->getValueType() == RegistryValueType_BINARY)
                            {
                                Sequence< sal_Int8 > aBytes( xKey2->getBinaryValue() );
                                typereg::Reader aReader(
                                    aBytes.getConstArray(), aBytes.getLength(),
                                    false, TYPEREG_VERSION_1);

                                if (aReader.getTypeClass() == RT_TYPE_MODULE ||
                                    aReader.getTypeClass() == RT_TYPE_CONSTANTS ||
                                    aReader.getTypeClass() == RT_TYPE_ENUM)
                                {
                                    OUString aFieldName( aKey.copy( nIndex+1, aKey.getLength() - nIndex -1 ) );
                                    sal_Int16 nPos = aReader.getFieldCount();
                                    while (nPos--)
                                    {
                                        if (aFieldName.equals(
                                                aReader.getFieldName(nPos)))
                                            break;
                                    }
                                    if (nPos >= 0)
                                        aRet = getRTValue(
                                            aReader.getFieldValue(nPos));
                                }
                            }
                        }
                    }
                }
            }
        }
        catch ( InvalidRegistryException const & )
        {
            OSL_ENSURE( sal_False,
                        "ProviderImpl::getByHierarchicalName "
                        "- Caught InvalidRegistryException!" );

            // openKey, closeKey, getValueType, getBinaryValue, isValid

            // Don't stop iteration in this case.
        }
		catch ( NoSuchElementException const & )
		{
		}
    }
	return aRet;
}

Any SAL_CALL ProviderImpl::getByHierarchicalName( const OUString & rName )
	throw(::com::sun::star::uno::RuntimeException, com::sun::star::container::NoSuchElementException)
{
	Any aRet( getByHierarchicalNameImpl( rName ) );

    if ( !aRet.hasValue() )
        throw NoSuchElementException(
            rName, static_cast< cppu::OWeakObject * >( this  ) );

	return aRet;
}

//__________________________________________________________________________________________________
sal_Bool ProviderImpl::hasByHierarchicalName( const OUString & rName )
	throw(::com::sun::star::uno::RuntimeException)
{
	return getByHierarchicalNameImpl( rName ).hasValue();
}

// XTypeDescriptionEnumerationAccess
//__________________________________________________________________________________________________
// virtual
com::sun::star::uno::Reference< XTypeDescriptionEnumeration > SAL_CALL
ProviderImpl::createTypeDescriptionEnumeration(
        const OUString & moduleName,
        const Sequence< TypeClass > & types,
        TypeDescriptionSearchDepth depth )
    throw ( NoSuchTypeNameException,
            InvalidTypeNameException,
            RuntimeException )
{
    return com::sun::star::uno::Reference< XTypeDescriptionEnumeration >(
        TypeDescriptionEnumerationImpl::createInstance( getTDMgr(),
                                                        moduleName,
                                                        types,
                                                        depth,
                                                        _aBaseKeys ).get() );
}

//__________________________________________________________________________________________________
// global helper function

com::sun::star::uno::Reference< XTypeDescription > resolveTypedefs(
    com::sun::star::uno::Reference< XTypeDescription > const & type)
{
    com::sun::star::uno::Reference< XTypeDescription > resolved(type);
    while (resolved->getTypeClass() == TypeClass_TYPEDEF) {
        resolved = com::sun::star::uno::Reference< XIndirectTypeDescription >(
            resolved, UNO_QUERY_THROW)->getReferencedType();
    }
    return resolved;
}

com::sun::star::uno::Reference< XTypeDescription > createTypeDescription(
    const Sequence< sal_Int8 > & rData,
    const com::sun::star::uno::Reference< XHierarchicalNameAccess > & xNameAccess,
    bool bReturnEmptyRefForUnknownType )
{
    typereg::Reader aReader(
        rData.getConstArray(), rData.getLength(), false, TYPEREG_VERSION_1);

    OUString aName( aReader.getTypeName().replace( '/', '.' ) );

    switch (aReader.getTypeClass())
    {
        case RT_TYPE_INTERFACE:
        {
            sal_uInt16 n = aReader.getSuperTypeCount();
            com::sun::star::uno::Sequence< rtl::OUString > aBaseTypeNames(n);
            {for (sal_uInt16 i = 0; i < n; ++i) {
                aBaseTypeNames[i] = aReader.getSuperTypeName(i).replace(
                    '/', '.');
            }}
            sal_uInt16 n2 = aReader.getReferenceCount();
            com::sun::star::uno::Sequence< rtl::OUString >
                aOptionalBaseTypeNames(n2);
            {for (sal_uInt16 i = 0; i < n2; ++i) {
                OSL_ASSERT(
                    aReader.getReferenceSort(i) == RT_REF_SUPPORTS
                    && aReader.getReferenceFlags(i) == RT_ACCESS_OPTIONAL);
                aOptionalBaseTypeNames[i] = aReader.getReferenceTypeName(i);
            }}
            return com::sun::star::uno::Reference< XTypeDescription >(
                new InterfaceTypeDescriptionImpl( xNameAccess,
                                                  aName,
                                                  aBaseTypeNames,
                                                  aOptionalBaseTypeNames,
                                                  rData,
                                                  aReader.isPublished() ) );
        }

        case RT_TYPE_MODULE:
        {
            com::sun::star::uno::Reference<
                XTypeDescriptionEnumerationAccess > xTDEA(
                    xNameAccess, UNO_QUERY );

            OSL_ENSURE( xTDEA.is(),
                        "No XTypeDescriptionEnumerationAccess!" );

            return com::sun::star::uno::Reference< XTypeDescription >(
                new ModuleTypeDescriptionImpl( xTDEA, aName ) );
        }

        case RT_TYPE_STRUCT:
            {
                rtl::OUString superTypeName;
                if (aReader.getSuperTypeCount() == 1) {
                    superTypeName = aReader.getSuperTypeName(0).replace(
                        '/', '.');
                }
                return com::sun::star::uno::Reference< XTypeDescription >(
                    new stoc::registry_tdprovider::StructTypeDescription(
                        xNameAccess, aName, superTypeName, rData,
                        aReader.isPublished()));
            }

        case RT_TYPE_ENUM:
            return com::sun::star::uno::Reference< XTypeDescription >(
                new EnumTypeDescriptionImpl( xNameAccess,
                                             aName,
                                             getRTValueAsInt32(
                                                aReader.getFieldValue( 0 ) ),
                                             rData, aReader.isPublished() ) );

        case RT_TYPE_EXCEPTION:
            {
                rtl::OUString superTypeName;
                if (aReader.getSuperTypeCount() == 1) {
                    superTypeName = aReader.getSuperTypeName(0).replace(
                        '/', '.');
                }
                return com::sun::star::uno::Reference< XTypeDescription >(
                    new CompoundTypeDescriptionImpl(
                        xNameAccess, TypeClass_EXCEPTION, aName, superTypeName,
                        rData, aReader.isPublished()));
            }

        case RT_TYPE_TYPEDEF:
            return com::sun::star::uno::Reference< XTypeDescription >(
                new TypedefTypeDescriptionImpl( xNameAccess,
                                                aName,
                                                aReader.getSuperTypeName(0)
                                                    .replace( '/', '.' ),
                                                aReader.isPublished() ) );
        case RT_TYPE_SERVICE:
            return com::sun::star::uno::Reference< XTypeDescription >(
                new ServiceTypeDescriptionImpl(
                    xNameAccess, aName, rData, aReader.isPublished() ) );

        case RT_TYPE_CONSTANTS:
            return com::sun::star::uno::Reference< XTypeDescription >(
                new ConstantsTypeDescriptionImpl(
                    aName, rData, aReader.isPublished() ) );

        case RT_TYPE_SINGLETON:
            return com::sun::star::uno::Reference< XTypeDescription >(
                new SingletonTypeDescriptionImpl( xNameAccess,
                                                  aName,
                                                  aReader.getSuperTypeName(0)
                                                    .replace( '/', '.' ),
                                                  aReader.isPublished() ) );
        case RT_TYPE_INVALID:
        case RT_TYPE_OBJECT:      // deprecated and not used
        case RT_TYPE_UNION:       // deprecated and not used
            OSL_ENSURE( sal_False, "createTypeDescription - Unsupported Type!" );
            break;

        default:
            OSL_ENSURE( sal_False, "createTypeDescription - Unknown Type!" );
            break;
    }

    // Unknown type.

    if ( bReturnEmptyRefForUnknownType )
        return com::sun::star::uno::Reference< XTypeDescription >();

    return com::sun::star::uno::Reference< XTypeDescription >(
                new TypeDescriptionImpl( TypeClass_UNKNOWN, aName ) );
}

}

namespace stoc_bootstrap
{
//==================================================================================================
com::sun::star::uno::Reference< XInterface > SAL_CALL ProviderImpl_create(
    com::sun::star::uno::Reference< XComponentContext > const & xContext )
	throw(::com::sun::star::uno::Exception)
{
    return com::sun::star::uno::Reference< XInterface >( *new stoc_rdbtdp::ProviderImpl( xContext ) );
}
}
