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

#include "sal/config.h"
#include "cppuhelper/factory.hxx"
#include "cppuhelper/implementationentry.hxx"
#include "cppuhelper/implbase3.hxx"
#include "com/sun/star/lang/XServiceInfo.hpp"
#include "com/sun/star/inspection/XStringRepresentation.hpp"
#include "com/sun/star/lang/XInitialization.hpp"
#include "com/sun/star/script/XTypeConverter.hpp"
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
#include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
#include <com/sun/star/beans/XIntrospection.hpp>
#include <com/sun/star/util/DateTime.hpp>
#include <com/sun/star/util/Date.hpp>
#include <com/sun/star/util/Time.hpp>
#include <comphelper/sequence.hxx>
#include <connectivity/dbconversion.hxx>
#ifndef _EXTENSIONS_PROPCTRLR_MODULEPRC_HXX_
#include "modulepcr.hxx"
#endif
#ifndef _EXTENSIONS_FORMCTRLR_PROPRESID_HRC_
#include "formresid.hrc"
#endif
#include <tools/debug.hxx>
#include <tools/string.hxx>
#include <tools/StringListResource.hxx>
#include <comphelper/types.hxx>
#ifndef _EXTENSIONS_PROPCTRLR_MODULEPCR_HXX_
#include "modulepcr.hxx"
#endif

#include <functional>
#include <algorithm>

// component helper namespace
namespace comp_StringRepresentation {

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

// component and service helper functions:
::rtl::OUString SAL_CALL _getImplementationName();
uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames();
uno::Reference< uno::XInterface > SAL_CALL _create( uno::Reference< uno::XComponentContext > const & context );

} // closing component helper namespace


namespace pcr{

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

class StringRepresentation:
    public ::cppu::WeakImplHelper3<
        lang::XServiceInfo,
        inspection::XStringRepresentation,
        lang::XInitialization>
{
public:
    explicit StringRepresentation(uno::Reference< uno::XComponentContext > const & context);

    // lang::XServiceInfo:
    virtual ::rtl::OUString SAL_CALL getImplementationName() throw (uno::RuntimeException);
    virtual ::sal_Bool SAL_CALL supportsService(const ::rtl::OUString & ServiceName) throw (uno::RuntimeException);
    virtual uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (uno::RuntimeException);

    // inspection::XStringRepresentation:
    virtual ::rtl::OUString SAL_CALL convertToControlValue(const uno::Any & PropertyValue) throw (uno::RuntimeException, uno::Exception);
    virtual uno::Any SAL_CALL convertToPropertyValue(const ::rtl::OUString & ControlValue, const uno::Type & ControlValueType) throw (uno::RuntimeException, uno::Exception);

    // lang::XInitialization:
    virtual void SAL_CALL initialize(const uno::Sequence< uno::Any > & aArguments) throw (uno::RuntimeException, uno::Exception);

private:
    StringRepresentation(StringRepresentation &); // not defined
    void operator =(StringRepresentation &); // not defined

    virtual ~StringRepresentation() {}

    /** converts a generic value into a string representation

        If you want to convert values whose string representation does not depend
        on a concrete property, use this version

        @return <TRUE/>
            if and only if the value could be converted
    */
    bool            convertGenericValueToString(
                        const uno::Any&   _rValue,
                                ::rtl::OUString&              _rStringRep
                    );

    /** converts string representation into generic value

        If you want to convert values whose string representation does not depend
        on a concrete property, use this version

        @return <TRUE/>
            if and only if the value could be converted
    */
    bool            convertStringToGenericValue(
                        const ::rtl::OUString&              _rStringRep,
                                uno::Any&   _rValue,
                        const uno::Type& _rTargetType
                    );

    /** uses the simple convert method from the type converter
    *
    * \param _rValue the value to be converted
    * \return the converted string.
    */
    ::rtl::OUString convertSimpleToString( const uno::Any& _rValue );

    /** converts a string into his constant value if it exists, otherwise the type converter is used.
    * \param _rValue the value to be converted
    * \param _ePropertyType teh type of the propery to be converted into
    * \return the converted value
    */
    uno::Any convertStringToSimple( const ::rtl::OUString& _rValue,const uno::TypeClass& _ePropertyType );

    uno::Reference< uno::XComponentContext >                                m_xContext;
    uno::Reference< script::XTypeConverter >                                m_xTypeConverter;
    uno::Reference< reflection::XConstantsTypeDescription >                 m_xTypeDescription;
    uno::Sequence< ::rtl::OUString >                                        m_aValues;
    uno::Sequence< uno::Reference< reflection::XConstantTypeDescription> >  m_aConstants;

};

StringRepresentation::StringRepresentation(uno::Reference< uno::XComponentContext > const & context) :
    m_xContext(context)
{}

// com.sun.star.uno.XServiceInfo:
::rtl::OUString  SAL_CALL StringRepresentation::getImplementationName() throw (uno::RuntimeException)
{
    return comp_StringRepresentation::_getImplementationName();
}

::sal_Bool SAL_CALL StringRepresentation::supportsService(::rtl::OUString const & serviceName) throw (uno::RuntimeException)
{
    return ::comphelper::existsValue(serviceName,comp_StringRepresentation::_getSupportedServiceNames());
}

uno::Sequence< ::rtl::OUString >  SAL_CALL StringRepresentation::getSupportedServiceNames() throw (uno::RuntimeException)
{
    return comp_StringRepresentation::_getSupportedServiceNames();
}

// inspection::XStringRepresentation:
::rtl::OUString SAL_CALL StringRepresentation::convertToControlValue(const uno::Any & PropertyValue) throw (uno::RuntimeException, uno::Exception)
{
    ::rtl::OUString sReturn;
    if ( !convertGenericValueToString( PropertyValue, sReturn ) )
    {
        sReturn = convertSimpleToString( PropertyValue );
#ifdef DBG_UTIL
        if ( !sReturn.getLength() && PropertyValue.hasValue() )
        {
            ::rtl::OString sMessage( "StringRepresentation::convertPropertyValueToStringRepresentation: cannot convert values of type '" );
            sMessage += ::rtl::OString( PropertyValue.getValueType().getTypeName().getStr(), PropertyValue.getValueType().getTypeName().getLength(), RTL_TEXTENCODING_ASCII_US );
            sMessage += ::rtl::OString( "'!" );
            DBG_ERROR( sMessage.getStr() );
        }
#endif
    }

    return sReturn;
}

uno::Any SAL_CALL StringRepresentation::convertToPropertyValue(const ::rtl::OUString & ControlValue, const uno::Type & ControlValueType) throw (uno::RuntimeException, uno::Exception)
{
    uno::Any aReturn;

    uno::TypeClass ePropertyType = ControlValueType.getTypeClass();
	switch ( ePropertyType )
	{
	case uno::TypeClass_FLOAT:
	case uno::TypeClass_DOUBLE:
	case uno::TypeClass_BYTE:
	case uno::TypeClass_SHORT:
	case uno::TypeClass_LONG:
	case uno::TypeClass_HYPER:
	case uno::TypeClass_UNSIGNED_SHORT:
	case uno::TypeClass_UNSIGNED_LONG:
	case uno::TypeClass_UNSIGNED_HYPER:
		try
		{
            aReturn = convertStringToSimple(ControlValue, ePropertyType);
		}
		catch( const script::CannotConvertException& ) { }
        catch( const lang::IllegalArgumentException& ) { }
		break;

    default:
    #if OSL_DEBUG_LEVEL > 0
        bool bCanConvert =
    #endif
        convertStringToGenericValue( ControlValue, aReturn, ControlValueType );

    #if OSL_DEBUG_LEVEL > 0
        // could not convert ...
        if ( !bCanConvert && ControlValue.getLength() )
        {
            ::rtl::OString sMessage( "StringRepresentation::convertStringRepresentationToPropertyValue: cannot convert into values of type '" );
            sMessage += ::rtl::OString( ControlValueType.getTypeName().getStr(), ControlValueType.getTypeName().getLength(), RTL_TEXTENCODING_ASCII_US );
            sMessage += ::rtl::OString( "'!" );
            DBG_ERROR( sMessage.getStr() );
        }
    #endif
    }

    return aReturn;
}

// lang::XInitialization:
void SAL_CALL StringRepresentation::initialize(const uno::Sequence< uno::Any > & aArguments) throw (uno::RuntimeException, uno::Exception)
{
    sal_Int32 nLength = aArguments.getLength();
    if ( nLength )
    {
        const uno::Any* pIter = aArguments.getConstArray();
        m_xTypeConverter.set(*pIter++,uno::UNO_QUERY);
        if ( nLength == 3 )
        {
            ::rtl::OUString sConstantName;
            *pIter++ >>= sConstantName;
            *pIter >>= m_aValues;

            if ( m_xContext.is() )
            {
                uno::Reference< container::XHierarchicalNameAccess > xTypeDescProv(
                    m_xContext->getValueByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) ) ),
                    uno::UNO_QUERY_THROW );

                m_xTypeDescription.set( xTypeDescProv->getByHierarchicalName( sConstantName ), uno::UNO_QUERY_THROW );
                m_aConstants = m_xTypeDescription->getConstants();
            }
        }
    }
}
//------------------------------------------------------------------------
::rtl::OUString StringRepresentation::convertSimpleToString( const uno::Any& _rValue )
{
	::rtl::OUString sReturn;
	if ( m_xTypeConverter.is() && _rValue.hasValue() )
	{
		try
		{
            if ( m_aConstants.getLength() )
            {
                sal_Int16 nConstantValue = 0;
                if ( _rValue >>= nConstantValue )
                {
                    const uno::Reference< reflection::XConstantTypeDescription>* pIter = m_aConstants.getConstArray();
                    const uno::Reference< reflection::XConstantTypeDescription>* pEnd  = pIter + m_aConstants.getLength();
                    for(sal_Int32 i = 0;pIter != pEnd;++pIter,++i)
                    {
                        if ( (*pIter)->getConstantValue() == _rValue )
                        {
                            OSL_ENSURE(i < m_aValues.getLength() ,"StringRepresentation::convertSimpleToString: Index is not in range of m_aValues");
                            sReturn = m_aValues[i];
                            break;
                        }
                    }
                }
            }

            if ( !sReturn.getLength() )
			    m_xTypeConverter->convertToSimpleType( _rValue, uno::TypeClass_STRING ) >>= sReturn;
		}
		catch( script::CannotConvertException& ) { }
		catch( lang::IllegalArgumentException& ) { }
	}
	return sReturn;
}

//--------------------------------------------------------------------
namespace
{
    struct ConvertIntegerFromAndToString
    {
        ::rtl::OUString operator()( sal_Int32 _rIntValue ) const
        {
            return ::rtl::OUString::valueOf( (sal_Int32)_rIntValue );
        }
        sal_Int32 operator()( const ::rtl::OUString& _rStringValue ) const
        {
            return _rStringValue.toInt32();
        }
    };

    struct StringIdentity
    {
        ::rtl::OUString operator()( const ::rtl::OUString& _rValue ) const
        {
            return _rValue;
        }
    };

    template < class ElementType, class Transformer >
    ::rtl::OUString composeSequenceElements( const Sequence< ElementType >& _rElements, const Transformer& _rTransformer )
    {
		String sCompose;

		// loop through the elements and concatenate the string representations of the integers
		// (separated by a line break)
        const ElementType* pElements = _rElements.getConstArray();
        const ElementType* pElementsEnd = pElements + _rElements.getLength();
        for ( ; pElements != pElementsEnd; ++pElements )
        {
			sCompose += String( _rTransformer( *pElements ) );
			if ( pElements != pElementsEnd )
				sCompose += '\n';
        }

        return sCompose;
    }

    template < class ElementType, class Transformer >
    void splitComposedStringToSequence( const ::rtl::OUString& _rComposed, Sequence< ElementType >& _out_SplitUp, const Transformer& _rTransformer )
    {
        _out_SplitUp.realloc( 0 );
        if ( !_rComposed.getLength() )
            return;
        sal_Int32 tokenPos = 0;
        do
        {
            _out_SplitUp.realloc( _out_SplitUp.getLength() + 1 );
            _out_SplitUp[ _out_SplitUp.getLength() - 1 ] = (ElementType)_rTransformer( _rComposed.getToken( 0, '\n', tokenPos ) );
        }
        while ( tokenPos != -1 );
    }
}

//--------------------------------------------------------------------
bool StringRepresentation::convertGenericValueToString( const uno::Any& _rValue, ::rtl::OUString& _rStringRep )
{
    bool bCanConvert = true;

	switch ( _rValue.getValueTypeClass() )
	{
    case uno::TypeClass_STRING:
        _rValue >>= _rStringRep;
        break;

	case uno::TypeClass_BOOLEAN:
	{
        ::std::vector< ::rtl::OUString > aListEntries;
        tools::StringListResource aRes(PcrRes(RID_RSC_ENUM_YESNO),aListEntries);
        sal_Bool bValue = sal_False;
        _rValue >>= bValue;
        _rStringRep = bValue ? aListEntries[1] : aListEntries[0];
	}
	break;

	// some sequence types
	case uno::TypeClass_SEQUENCE:
	{
		Sequence< ::rtl::OUString > aStringValues;
        Sequence< sal_Int8 > aInt8Values;
		Sequence< sal_uInt16 > aUInt16Values;
        Sequence< sal_Int16 > aInt16Values;
		Sequence< sal_uInt32 > aUInt32Values;
        Sequence< sal_Int32 > aInt32Values;

        // string sequences
        if ( _rValue >>= aStringValues )
		{
            _rStringRep = composeSequenceElements( aStringValues, StringIdentity() );
		}
		// byte sequences
		else if ( _rValue >>= aInt8Values )
		{
            _rStringRep = composeSequenceElements( aInt8Values, ConvertIntegerFromAndToString() );
		}
		// uInt16 sequences
		else if ( _rValue >>= aUInt16Values )
		{
            _rStringRep = composeSequenceElements( aUInt16Values, ConvertIntegerFromAndToString() );
		}
		// Int16 sequences
		else if ( _rValue >>= aInt16Values )
		{
            _rStringRep = composeSequenceElements( aInt16Values, ConvertIntegerFromAndToString() );
		}
		// uInt32 sequences
		else if ( _rValue >>= aUInt32Values )
		{
            _rStringRep = composeSequenceElements( aUInt32Values, ConvertIntegerFromAndToString() );
		}
		// Int32 sequences
		else if ( _rValue >>= aInt32Values )
		{
            _rStringRep = composeSequenceElements( aInt32Values, ConvertIntegerFromAndToString() );
		}
        else
            bCanConvert = false;
	}
	break;
    case uno::TypeClass_CONSTANT:
        {
            int i = 0;
            ++i;
        }
        break;
    
	// some structs
    case uno::TypeClass_STRUCT:
        OSL_ENSURE( false, "StringRepresentation::convertGenericValueToString(STRUCT): this is dead code - isn't it?" );
        if ( _rValue.getValueType().equals( ::getCppuType( static_cast< util::Date* >( NULL ) ) ) )
        {
            // weird enough, the string representation of dates, as used
            // by the control displaying dates, and thus as passed through the layers,
            // is YYYYMMDD.
            util::Date aUnoDate;
            _rValue >>= aUnoDate;
            _rStringRep = ::dbtools::DBTypeConversion::toDateString(aUnoDate);
        }
        else if ( _rValue.getValueType().equals( ::getCppuType( static_cast< util::Time* >( NULL ) ) ) )
        {
            // similar for time (HHMMSSHH)
            util::Time aUnoTime;
            _rValue >>= aUnoTime;
            _rStringRep = ::dbtools::DBTypeConversion::toTimeString(aUnoTime);
        }
        else if ( _rValue.getValueType().equals( ::getCppuType( static_cast< util::DateTime* >( NULL ) ) ) )
        {
            util::DateTime aUnoDateTime;
            _rValue >>= aUnoDateTime;
            _rStringRep = ::dbtools::DBTypeConversion::toDateTimeString(aUnoDateTime);
        }
        else
            bCanConvert = false;
        break;

    default:
        bCanConvert = false;
        break;
	}

    return bCanConvert;
}
//------------------------------------------------------------------------
uno::Any StringRepresentation::convertStringToSimple( const ::rtl::OUString& _rValue,const uno::TypeClass& _ePropertyType )
{
	uno::Any aReturn;
	if ( m_xTypeConverter.is() && _rValue.getLength() )
	{
		try
		{
            if ( m_aConstants.getLength() && m_aValues.getLength() )
            {
                const ::rtl::OUString* pIter = m_aValues.getConstArray();
                const ::rtl::OUString* pEnd	  = pIter + m_aValues.getLength();
                for(sal_Int32 i = 0;pIter != pEnd;++pIter,++i)
                {
                    if ( *pIter == _rValue )
                    {
                        OSL_ENSURE(i < m_aConstants.getLength() ,"StringRepresentation::convertSimpleToString: Index is not in range of m_aValues");
                        aReturn <<= m_aConstants[i]->getConstantValue();
                        break;
                    }
                }
            }

            if ( !aReturn.hasValue() )
                aReturn = m_xTypeConverter->convertToSimpleType( makeAny( _rValue ), _ePropertyType );
		}
		catch( script::CannotConvertException& ) { }
		catch( lang::IllegalArgumentException& ) { }
	}
	return aReturn;
}
//--------------------------------------------------------------------
bool StringRepresentation::convertStringToGenericValue( const ::rtl::OUString& _rStringRep, uno::Any& _rValue, const uno::Type& _rTargetType )
{
    bool bCanConvert = true;

    switch ( _rTargetType.getTypeClass() )
    {
	case uno::TypeClass_STRING:
        _rValue <<= _rStringRep;
        break;

    case uno::TypeClass_BOOLEAN:
	{
        ::std::vector< ::rtl::OUString > aListEntries;
        tools::StringListResource aRes(PcrRes(RID_RSC_ENUM_YESNO),aListEntries);
        if ( aListEntries[0] == _rStringRep )
			_rValue <<= (sal_Bool)sal_False;
		else
			_rValue <<= (sal_Bool)sal_True;
	}
	break;

	case uno::TypeClass_SEQUENCE:
	{
		uno::Type aElementType = ::comphelper::getSequenceElementType( _rTargetType );

		String aStr( _rStringRep );
		switch ( aElementType.getTypeClass() )
		{
			case uno::TypeClass_STRING:
			{
                Sequence< ::rtl::OUString > aElements;
                splitComposedStringToSequence( aStr, aElements, StringIdentity() );
				_rValue <<= aElements;
			}
			break;
			case uno::TypeClass_SHORT:
			{
                Sequence< sal_Int16 > aElements;
                splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
				_rValue <<= aElements;
			}
			break;
			case uno::TypeClass_UNSIGNED_SHORT:
			{
                Sequence< sal_uInt16 > aElements;
                splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
				_rValue <<= aElements;
			}
			break;
			case uno::TypeClass_LONG:
			{
                Sequence< sal_Int32 > aElements;
                splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
				_rValue <<= aElements;
			}
			break;
			case uno::TypeClass_UNSIGNED_LONG:
			{
                Sequence< sal_uInt32 > aElements;
                splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
				_rValue <<= aElements;
			}
			break;
			case uno::TypeClass_BYTE:
			{
                Sequence< sal_Int8 > aElements;
                splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
				_rValue <<= aElements;
			}
			break;
            default:
                bCanConvert = false;
                break;
		}
	}
	break;

    case uno::TypeClass_STRUCT:
        OSL_ENSURE( false, "StringRepresentation::convertStringToGenericValue(STRUCT): this is dead code - isn't it?" );
        if ( _rTargetType.equals( ::getCppuType( static_cast< util::Date* >( NULL ) ) ) )
        {
            // weird enough, the string representation of dates, as used
            // by the control displaying dates, and thus as passed through the layers,
            // is YYYYMMDD.
            
            _rValue <<= ::dbtools::DBTypeConversion::toDate(_rStringRep);
        }
        else if ( _rTargetType.equals( ::getCppuType( static_cast< util::Time* >( NULL ) ) ) )
        {
            // similar for time (HHMMSSHH)
            _rValue <<= ::dbtools::DBTypeConversion::toTime(_rStringRep);
        }
        else if ( _rTargetType.equals( ::getCppuType( static_cast< util::DateTime* >( NULL ) ) ) )
        {
            _rValue <<= ::dbtools::DBTypeConversion::toDateTime(_rStringRep);
        }
        else
            bCanConvert = false;
        break;

    default:
        bCanConvert = false;
        break;
    }

    return bCanConvert;
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------
} // pcr
//------------------------------------------------------------------------


// component helper namespace
namespace comp_StringRepresentation {

::rtl::OUString SAL_CALL _getImplementationName() {
    return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
        "StringRepresentation"));
}

uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames()
{
    uno::Sequence< ::rtl::OUString > s(1);
    s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
        "com.sun.star.inspection.StringRepresentation"));
    return s;
}

uno::Reference< uno::XInterface > SAL_CALL _create(
    const uno::Reference< uno::XComponentContext > & context)
        SAL_THROW((uno::Exception))
{
    return static_cast< ::cppu::OWeakObject * >(new pcr::StringRepresentation(context));
}

} // closing component helper namespace

//------------------------------------------------------------------------
extern "C" void SAL_CALL createRegistryInfo_StringRepresentation()
{
    ::pcr::PcrModule::getInstance().registerImplementation(
            comp_StringRepresentation::_getImplementationName(),
            comp_StringRepresentation::_getSupportedServiceNames(),
            comp_StringRepresentation::_create
        );
}

