/**************************************************************
 *
 * 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 the type of the property 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
        );
}
