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

#include "ObjectNameProvider.hxx"
#include "ResId.hxx"
#include "Strings.hrc"
#include "macros.hxx"
#include "AxisHelper.hxx"
#include "ChartModelHelper.hxx"
#include "DiagramHelper.hxx"
#include "DataSeriesHelper.hxx"
#include "TitleHelper.hxx"
#include "AxisIndexDefines.hxx"
#include "ExplicitCategoriesProvider.hxx"
#include "CommonConverters.hxx"
#include "NumberFormatterWrapper.hxx"
#include "RegressionCurveHelper.hxx"
#include <rtl/math.hxx>
#include <tools/debug.hxx>
#include <tools/string.hxx>

#include <com/sun/star/chart2/XTitle.hpp>
#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>

//.............................................................................
namespace chart
{
//.............................................................................
using namespace ::com::sun::star;
using namespace ::com::sun::star::chart2;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Any;
using rtl::OUString;

namespace
{

OUString lcl_getDataSeriesName( const rtl::OUString& rObjectCID, const Reference< frame::XModel >& xChartModel )
{
    OUString aRet;

    Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
    Reference< XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ), uno::UNO_QUERY );
    if( xDiagram.is() && xSeries.is() )
    {
        Reference< XChartType > xChartType( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries ) );
        if( xChartType.is() )
        {
            aRet = ::chart::DataSeriesHelper::getDataSeriesLabel(
                    xSeries, xChartType->getRoleOfSequenceForSeriesLabel() ) ;
        }
    }

    return aRet;
}

OUString lcl_getFullSeriesName( const rtl::OUString& rObjectCID, const Reference< frame::XModel >& xChartModel )
{
    OUString aRet = String(SchResId(STR_TIP_DATASERIES));
    OUString aWildcard( C2U("%SERIESNAME") );
    sal_Int32 nIndex = aRet.indexOf( aWildcard );
    if( nIndex != -1 )
        aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), lcl_getDataSeriesName( rObjectCID, xChartModel ) );
    return aRet;
}

void lcl_addText( OUString& rOut, const OUString& rSeparator, const OUString& rNext )
{
    if( !rOut.isEmpty() && !rNext.isEmpty() )
        rOut+=rSeparator;
    if( !rNext.isEmpty() )
        rOut+=rNext;
}

OUString lcl_getDataPointValueText( const Reference< XDataSeries >& xSeries, sal_Int32 nPointIndex,
                                    const Reference< XCoordinateSystem >& xCooSys,
                                    const Reference< frame::XModel >& xChartModel )
{

    OUString aRet;

    Reference<data::XDataSource> xDataSource(
            uno::Reference<data::XDataSource>( xSeries, uno::UNO_QUERY ) );
    if(!xDataSource.is())
        return aRet;

    Sequence< Reference< data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() );

    rtl::OUString aX, aY, aY_Min, aY_Max, aY_First, aY_Last, a_Size;
    double fValue = 0;

    uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( xChartModel, uno::UNO_QUERY );
    NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier );
    sal_Int32 nLabelColor = 0;//dummy
    bool bColorChanged;//dummy

    for(sal_Int32 nN = aDataSequences.getLength();nN--;)
    {
        uno::Reference<data::XDataSequence>  xDataSequence( aDataSequences[nN]->getValues());
        if( !xDataSequence.is() )
            continue;
        Sequence< Any > aData( xDataSequence->getData() );
        if( nPointIndex >= aData.getLength() )
            continue;
        uno::Reference<beans::XPropertySet> xProp(xDataSequence, uno::UNO_QUERY );
	    if( xProp.is())
	    {
		    try
		    {
                uno::Any aARole = xProp->getPropertyValue( C2U( "Role" ) );
                rtl::OUString aRole;
                aARole >>= aRole;

                if( aRole.equals(C2U("values-x")) )
                {
                    aData[nPointIndex]>>= fValue;
                    sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
                    aX = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
                }
                else if( aRole.equals(C2U("values-y")) )
                {
                    aData[nPointIndex]>>= fValue;
                    sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
                    aY = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
                }
                else if( aRole.equals(C2U("values-first")) )
                {
                    aData[nPointIndex]>>= fValue;
                    sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
                    aY_First = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
                }
                else if( aRole.equals(C2U("values-min")) )
                {
                    aData[nPointIndex]>>= fValue;
                    sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
                    aY_Min = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
                }
                else if( aRole.equals(C2U("values-max")) )
                {
                    aData[nPointIndex]>>= fValue;
                    sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
                    aY_Max = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
                }
                else if( aRole.equals(C2U("values-last")) )
                {
                    aData[nPointIndex]>>= fValue;
                    sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
                    aY_Last = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
                }
                else if( aRole.equals(C2U("values-size")) )
                {
                    aData[nPointIndex]>>= fValue;
                    sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
                    a_Size = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
                }
            }
            catch( uno::Exception& e )
		    {
                ASSERT_EXCEPTION( e );
            }
        }
    }

    if( aX.isEmpty() )
    {
        aRet = ExplicitCategoriesProvider::getCategoryByIndex( xCooSys, xChartModel, nPointIndex );
    }
    else
    {
        aRet = aX;
    }

    OUString aSeparator(C2U(" "));

    lcl_addText( aRet, aSeparator, aY );
    lcl_addText( aRet, aSeparator, aY_First );
    lcl_addText( aRet, aSeparator, aY_Min );
    lcl_addText( aRet, aSeparator, aY_Max );
    lcl_addText( aRet, aSeparator, aY_Last );
    lcl_addText( aRet, aSeparator, a_Size );

    return aRet;
}

} //end anonymous namespace

rtl::OUString ObjectNameProvider::getName( ObjectType eObjectType, bool bPlural )
{
    rtl::OUString aRet;
    switch( eObjectType )
    {
        case OBJECTTYPE_PAGE:
                aRet=String(SchResId(STR_OBJECT_PAGE));
                break;
        case OBJECTTYPE_TITLE:
            {
                if(bPlural)
                    aRet=String(SchResId(STR_OBJECT_TITLES));
                else
                    aRet=String(SchResId(STR_OBJECT_TITLE));
            }
                break;
        case OBJECTTYPE_LEGEND:
                aRet=String(SchResId(STR_OBJECT_LEGEND));
                break;
        case OBJECTTYPE_LEGEND_ENTRY:
                aRet=String(SchResId(STR_OBJECT_LEGEND_SYMBOL));//@todo change string if we do differenciate symbol and legend entry in future
                break;
        case OBJECTTYPE_DIAGRAM:
                aRet=String(SchResId(STR_OBJECT_DIAGRAM));
                break;
        case OBJECTTYPE_DIAGRAM_WALL:
                aRet=String(SchResId(STR_OBJECT_DIAGRAM_WALL));
                break;
        case OBJECTTYPE_DIAGRAM_FLOOR:
                aRet=String(SchResId(STR_OBJECT_DIAGRAM_FLOOR));
                break;
        case OBJECTTYPE_AXIS:
            {
                if(bPlural)
                    aRet=String(SchResId(STR_OBJECT_AXES));
                else
                    aRet=String(SchResId(STR_OBJECT_AXIS));
            }
                break;
        case OBJECTTYPE_AXIS_UNITLABEL:
                aRet=String(SchResId(STR_OBJECT_LABEL));//@todo maybe a more concrete name
                break;
        case OBJECTTYPE_GRID:
        case OBJECTTYPE_SUBGRID: //maybe todo: different names for subgrids
            {
                if(bPlural)
                    aRet=String(SchResId(STR_OBJECT_GRIDS));
                else
                    aRet=String(SchResId(STR_OBJECT_GRID));
            }
                break;
        case OBJECTTYPE_DATA_SERIES:
            {
                if(bPlural)
                    aRet=String(SchResId(STR_OBJECT_DATASERIES_PLURAL));
                else
                    aRet=String(SchResId(STR_OBJECT_DATASERIES));
            }
                break;
        case OBJECTTYPE_DATA_POINT:
            {
                if(bPlural)
                    aRet=String(SchResId(STR_OBJECT_DATAPOINTS));
                else
                    aRet=String(SchResId(STR_OBJECT_DATAPOINT));
            }
                break;
        case OBJECTTYPE_DATA_LABELS:
                aRet=String(SchResId(STR_OBJECT_DATALABELS));
                break;
        case OBJECTTYPE_DATA_LABEL:
                aRet=String(SchResId(STR_OBJECT_LABEL));
                break;
        case OBJECTTYPE_DATA_ERRORS:
                aRet=String(SchResId(STR_OBJECT_ERROR_BARS));//@todo? maybe distinguish plural singular
                break;
        case OBJECTTYPE_DATA_ERRORS_X:
                aRet=String(SchResId(STR_OBJECT_ERROR_BARS));//@todo? maybe specialize in future
                break;
        case OBJECTTYPE_DATA_ERRORS_Y:
                aRet=String(SchResId(STR_OBJECT_ERROR_BARS));//@todo? maybe specialize in future
                break;
        case OBJECTTYPE_DATA_ERRORS_Z:
                aRet=String(SchResId(STR_OBJECT_ERROR_BARS));//@todo? maybe specialize in future
                break;
        case OBJECTTYPE_DATA_AVERAGE_LINE:
                aRet=String(SchResId(STR_OBJECT_AVERAGE_LINE));
                break;
        case OBJECTTYPE_DATA_CURVE:
            {
                if(bPlural)
                    aRet=String(SchResId(STR_OBJECT_CURVES));
                else
                    aRet=String(SchResId(STR_OBJECT_CURVE));
            }
                break;
        case OBJECTTYPE_DATA_STOCK_RANGE:
                //aRet=String(SchResId());
                break;
        case OBJECTTYPE_DATA_STOCK_LOSS:
                aRet=String(SchResId(STR_OBJECT_STOCK_LOSS));
                break;
        case OBJECTTYPE_DATA_STOCK_GAIN:
                aRet=String(SchResId(STR_OBJECT_STOCK_GAIN));
                break;
        case OBJECTTYPE_DATA_CURVE_EQUATION:
                aRet=String(SchResId(STR_OBJECT_CURVE_EQUATION));
                break;
        default: //OBJECTTYPE_UNKNOWN
            ;
    }
    return aRet;
}

rtl::OUString ObjectNameProvider::getAxisName( const rtl::OUString& rObjectCID
                        , const uno::Reference< frame::XModel >& xChartModel  )
{
    rtl::OUString aRet;

    

    Reference< XAxis > xAxis(
        ObjectIdentifier::getObjectPropertySet( rObjectCID , xChartModel ), uno::UNO_QUERY );

    sal_Int32 nCooSysIndex = 0;
    sal_Int32 nDimensionIndex = 0;
    sal_Int32 nAxisIndex = 0;
    AxisHelper::getIndicesForAxis( xAxis, ChartModelHelper::findDiagram( xChartModel ), nCooSysIndex, nDimensionIndex, nAxisIndex );
    
    switch(nDimensionIndex)
    {
        case 0://x-axis
            if( nAxisIndex == 0 )
                aRet=String(SchResId(STR_OBJECT_AXIS_X));
            else
                aRet=String(SchResId(STR_OBJECT_SECONDARY_X_AXIS));
            break;
        case 1://y-axis
            if( nAxisIndex == 0 )
                aRet=String(SchResId(STR_OBJECT_AXIS_Y));
            else
                aRet=String(SchResId(STR_OBJECT_SECONDARY_Y_AXIS));
            break;
        case 2://z-axis
            aRet=String(SchResId(STR_OBJECT_AXIS_Z));
            break;
        default://axis
            aRet=String(SchResId(STR_OBJECT_AXIS));
            break;
    }
    
    return aRet;
}

OUString ObjectNameProvider::getTitleNameByType( TitleHelper::eTitleType eType )
{
    OUString aRet;

    switch(eType)
    {
        case TitleHelper::MAIN_TITLE:
            aRet=String(SchResId(STR_OBJECT_TITLE_MAIN));
            break;
        case TitleHelper::SUB_TITLE:
            aRet=String(SchResId(STR_OBJECT_TITLE_SUB));
            break;
        case TitleHelper::X_AXIS_TITLE:
            aRet=String(SchResId(STR_OBJECT_TITLE_X_AXIS));
            break;
        case TitleHelper::Y_AXIS_TITLE:
            aRet=String(SchResId(STR_OBJECT_TITLE_Y_AXIS));
            break;
        case TitleHelper::Z_AXIS_TITLE:
            aRet=String(SchResId(STR_OBJECT_TITLE_Z_AXIS));
            break;
        case TitleHelper::SECONDARY_X_AXIS_TITLE:
            aRet=String(SchResId(STR_OBJECT_TITLE_SECONDARY_X_AXIS));
            break;
        case TitleHelper::SECONDARY_Y_AXIS_TITLE:
            aRet=String(SchResId(STR_OBJECT_TITLE_SECONDARY_Y_AXIS));
            break;
        default:
            DBG_ERROR("unknown title type");
            break;
    }
     
    if( aRet.isEmpty() )
        aRet=String(SchResId(STR_OBJECT_TITLE));

    return aRet;
}

OUString ObjectNameProvider::getTitleName( const OUString& rObjectCID
                        , const Reference< frame::XModel >& xChartModel )
{
    OUString aRet;

    Reference< XTitle > xTitle(
        ObjectIdentifier::getObjectPropertySet( rObjectCID , xChartModel ), uno::UNO_QUERY );
    if( xTitle.is() )
    {
        TitleHelper::eTitleType eType;
        if( TitleHelper::getTitleType( eType, xTitle, xChartModel ) )
            aRet = ObjectNameProvider::getTitleNameByType( eType );
    }
    if( aRet.isEmpty() )
        aRet=String(SchResId(STR_OBJECT_TITLE));

    return aRet;
}

rtl::OUString ObjectNameProvider::getGridName( const rtl::OUString& rObjectCID
                        , const uno::Reference< frame::XModel >& xChartModel )
{
    rtl::OUString aRet;
    

    sal_Int32 nCooSysIndex = -1;
    sal_Int32 nDimensionIndex = -1;
    sal_Int32 nAxisIndex = -1;
    Reference< XAxis > xAxis( ObjectIdentifier::getAxisForCID( rObjectCID , xChartModel ) );
    AxisHelper::getIndicesForAxis( xAxis, ChartModelHelper::findDiagram( xChartModel )
              , nCooSysIndex , nDimensionIndex, nAxisIndex );

    bool bMainGrid = (ObjectIdentifier::getObjectType( rObjectCID ) == OBJECTTYPE_GRID);

    if( bMainGrid )
    {
        switch(nDimensionIndex)
        {
            case 0://x-axis
                aRet=String(SchResId(STR_OBJECT_GRID_MAJOR_X));
                break;
            case 1://y-axis
                aRet=String(SchResId(STR_OBJECT_GRID_MAJOR_Y));
                break;
            case 2://z-axis
                aRet=String(SchResId(STR_OBJECT_GRID_MAJOR_Z));
                break;
            default://axis
                aRet=String(SchResId(STR_OBJECT_GRID));
                break;
        }
    }
    else
    {
        switch(nDimensionIndex)
        {
            case 0://x-axis
                aRet=String(SchResId(STR_OBJECT_GRID_MINOR_X));
                break;
            case 1://y-axis
                aRet=String(SchResId(STR_OBJECT_GRID_MINOR_Y));
                break;
            case 2://z-axis
                aRet=String(SchResId(STR_OBJECT_GRID_MINOR_Z));
                break;
            default://axis
                aRet=String(SchResId(STR_OBJECT_GRID));
                break;
        }
    }
    return aRet;
}

rtl::OUString ObjectNameProvider::getHelpText( const rtl::OUString& rObjectCID, const Reference< chart2::XChartDocument >& xChartDocument, bool bVerbose )
{
    return getHelpText( rObjectCID, Reference< frame::XModel >( xChartDocument, uno::UNO_QUERY ), bVerbose );
}

rtl::OUString ObjectNameProvider::getHelpText( const rtl::OUString& rObjectCID, const Reference< frame::XModel >& xChartModel, bool bVerbose )
{
    rtl::OUString aRet;
    ObjectType eObjectType( ObjectIdentifier::getObjectType(rObjectCID) );
    if( OBJECTTYPE_AXIS == eObjectType )
    {
        aRet=ObjectNameProvider::getAxisName( rObjectCID, xChartModel );
    }
    else if( OBJECTTYPE_GRID == eObjectType
        || OBJECTTYPE_SUBGRID == eObjectType )
    {
        aRet=ObjectNameProvider::getGridName( rObjectCID, xChartModel );
    }
    else if( OBJECTTYPE_TITLE == eObjectType )
    {
        aRet=ObjectNameProvider::getTitleName( rObjectCID, xChartModel );
    }
    else if( OBJECTTYPE_DATA_SERIES == eObjectType )
    {
        aRet = lcl_getFullSeriesName( rObjectCID, xChartModel );
    }
    else if( OBJECTTYPE_DATA_POINT == eObjectType )
    {
        if( bVerbose )
        {
            OUString aNewLine(C2U("\n"));

            aRet=String(SchResId(STR_TIP_DATAPOINT_INDEX));
            aRet+=aNewLine;
            aRet+=String(SchResId(STR_TIP_DATASERIES));
            aRet+=aNewLine;
            aRet+=String(SchResId(STR_TIP_DATAPOINT_VALUES));
        }
        else
            aRet=String(SchResId(STR_TIP_DATAPOINT));

        Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
        Reference< XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ), uno::UNO_QUERY );
        if( xDiagram.is() && xSeries.is() )
        {
            sal_Int32 nPointIndex( ObjectIdentifier::getParticleID(rObjectCID).toInt32() );

            //replace data point index
            sal_Int32 nIndex = -1;
            OUString aWildcard( C2U("%POINTNUMBER") );
            nIndex = aRet.indexOf( aWildcard );
            if( nIndex != -1 )
            {
                aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), OUString::valueOf(nPointIndex+1) );
            }

            //replace data series index
            aWildcard = C2U("%SERIESNUMBER");
            nIndex = aRet.indexOf( aWildcard );
            if( nIndex != -1 )
            {
                ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector(
                    DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
                sal_Int32 nSeriesIndex = -1;
                for( nSeriesIndex=aSeriesVector.size();nSeriesIndex--;)
                {
                    if( aSeriesVector[nSeriesIndex] == xSeries )
                    {
                        break;
                    }
                }
                
                OUString aReplacement( OUString::valueOf(nSeriesIndex+1) );
                aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), aReplacement );
            }

            //replace point values
            aWildcard = C2U("%POINTVALUES");
            nIndex = aRet.indexOf( aWildcard );
            if( nIndex != -1 )
                aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), lcl_getDataPointValueText(
                xSeries,nPointIndex, DataSeriesHelper::getCoordinateSystemOfSeries(xSeries, xDiagram), xChartModel ) );

            //replace series name
            aWildcard = C2U("%SERIESNAME");
            nIndex = aRet.indexOf( aWildcard );
            if( nIndex != -1 )
                aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), lcl_getDataSeriesName( rObjectCID, xChartModel ) );
        }
    }
    /*
    else if( OBJECTTYPE_DIAGRAM == eObjectType )
    {
        //todo different names for different diagram types ???
        //or different names for series of diferent charttypes
    }
    */
    else if( OBJECTTYPE_DATA_CURVE == eObjectType )
    {
        if( bVerbose )
        {
            aRet = String( SchResId( STR_OBJECT_CURVE_WITH_PARAMETERS ));
            Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ));
            Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY );
            if( xCurveCnt.is())
            {
                Reference< chart2::XRegressionCurve > xCurve( RegressionCurveHelper::getFirstCurveNotMeanValueLine( xCurveCnt ));
                if( xCurve.is())
                {
                    try
                    {
                        Reference< chart2::XRegressionCurveCalculator > xCalculator( xCurve->getCalculator(), uno::UNO_QUERY_THROW );
                        RegressionCurveHelper::initializeCurveCalculator( xCalculator, xSeries, xChartModel );

                        // replace formula
                        sal_Int32 nIndex = -1;
                        OUString aWildcard( C2U("%FORMULA") );
                        nIndex = aRet.indexOf( aWildcard );
                        if( nIndex != -1 )
                            aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), xCalculator->getRepresentation());

                        // replace r^2
                        aWildcard = C2U("%RSQUARED");
                        nIndex = aRet.indexOf( aWildcard );
                        if( nIndex != -1 )
                        {
                            sal_Unicode aDecimalSep( '.' );
                            //@todo: enable this code when a localized decimal
                            //separator is also available for the formula
//                             SvtSysLocale aSysLocale;
//                             OUString aSep( aSysLocale.GetLocaleData().getNumDecimalSep());
//                             if( aSep.getLength() == 1 )
//                                 aDecimalSep = aSep.toChar();
                            double fR( xCalculator->getCorrelationCoefficient());
                            aRet = aRet.replaceAt(
                                nIndex, aWildcard.getLength(),
                                ::rtl::math::doubleToUString(
                                    fR*fR, rtl_math_StringFormat_G, 4, aDecimalSep, true ));
                        }
                    }
                    catch( const uno::Exception & ex )
                    {
                        ASSERT_EXCEPTION( ex );
                    }
                }
            }
        }
        else
        {
            // non-verbose
            aRet = ObjectNameProvider::getName( eObjectType, false );
        }
    }
    else if( OBJECTTYPE_DATA_AVERAGE_LINE == eObjectType )
    {
        if( bVerbose )
        {
            aRet = String( SchResId( STR_OBJECT_AVERAGE_LINE_WITH_PARAMETERS ));
            Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ));
            Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY );
            if( xCurveCnt.is())
            {
                Reference< chart2::XRegressionCurve > xCurve( RegressionCurveHelper::getMeanValueLine( xCurveCnt ));
                if( xCurve.is())
                {
                    try
                    {
                        Reference< chart2::XRegressionCurveCalculator > xCalculator( xCurve->getCalculator(), uno::UNO_QUERY_THROW );
                        RegressionCurveHelper::initializeCurveCalculator( xCalculator, xSeries, xChartModel );

                        sal_Unicode aDecimalSep( '.' );
                        // replace average value
//                             SvtSysLocale aSysLocale;
//                             OUString aSep( aSysLocale.GetLocaleData().getNumDecimalSep());
//                             if( aSep.getLength() == 1 )
//                                 aDecimalSep = aSep.toChar();

                        sal_Int32 nIndex = -1;
                        OUString aWildcard( C2U("%AVERAGE_VALUE") );
                        nIndex = aRet.indexOf( aWildcard );
                        // as the curve is constant, the value at any x-value is ok
                        if( nIndex != -1 )
                        {
                            const double fMeanValue( xCalculator->getCurveValue( 0.0 ));
                            aRet = aRet.replaceAt(
                                nIndex, aWildcard.getLength(),
                                ::rtl::math::doubleToUString(
                                    fMeanValue, rtl_math_StringFormat_G, 4, aDecimalSep, true ));
                        }

                        // replace standard deviation
                        aWildcard = C2U("%STD_DEVIATION");
                        nIndex = aRet.indexOf( aWildcard );
                        if( nIndex != -1 )
                        {
                            const double fStdDev( xCalculator->getCorrelationCoefficient());
                            aRet = aRet.replaceAt(
                                nIndex, aWildcard.getLength(),
                                ::rtl::math::doubleToUString(
                                    fStdDev, rtl_math_StringFormat_G, 4, aDecimalSep, true ));
                        }
                    }
                    catch( const uno::Exception & ex )
                    {
                        ASSERT_EXCEPTION( ex );
                    }
                }
            }
        }
        else
        {
            // non-verbose
            aRet = ObjectNameProvider::getName( eObjectType, false );
        }
    }
    else
    {
        aRet = ObjectNameProvider::getName( eObjectType, false );
    }
    return aRet;
}

rtl::OUString ObjectNameProvider::getSelectedObjectText( const rtl::OUString & rObjectCID, const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument >& xChartDocument )
{
    rtl::OUString aRet;
    ObjectType eObjectType( ObjectIdentifier::getObjectType(rObjectCID) );
    Reference< frame::XModel > xChartModel( xChartDocument, uno::UNO_QUERY );

    if( OBJECTTYPE_DATA_POINT == eObjectType )
    {
        aRet = String( SchResId( STR_STATUS_DATAPOINT_MARKED ));

        Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
        Reference< XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ), uno::UNO_QUERY );
        if( xDiagram.is() && xSeries.is() )
        {
            sal_Int32 nPointIndex( ObjectIdentifier::getParticleID(rObjectCID).toInt32() );

            // replace data point index
            replaceParamterInString( aRet, C2U("%POINTNUMBER"), OUString::valueOf( nPointIndex + 1 ));

            // replace data series index
            {
                ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector(
                    DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
                sal_Int32 nSeriesIndex = -1;
                for( nSeriesIndex=aSeriesVector.size();nSeriesIndex--;)
                {
                    if( aSeriesVector[nSeriesIndex] == xSeries )
                        break;
                }
                replaceParamterInString( aRet, C2U("%SERIESNUMBER"), OUString::valueOf( nSeriesIndex + 1 ) );
            }

            // replace point value
            replaceParamterInString( aRet, C2U("%POINTVALUES"), lcl_getDataPointValueText(
                xSeries, nPointIndex, DataSeriesHelper::getCoordinateSystemOfSeries(xSeries, xDiagram), xChartModel ) );
        }
    }
    else
    {
        // use the verbose text including the formula for trend lines
        const bool bVerbose( OBJECTTYPE_DATA_CURVE == eObjectType || OBJECTTYPE_DATA_AVERAGE_LINE == eObjectType );
        const OUString aHelpText( getHelpText( rObjectCID, xChartModel, bVerbose ));
        if( !aHelpText.isEmpty() )
        {
            aRet = String( SchResId( STR_STATUS_OBJECT_MARKED ));
            replaceParamterInString( aRet, C2U("%OBJECTNAME"), aHelpText );
        }
    }

    return aRet;
}

rtl::OUString ObjectNameProvider::getNameForCID(
    const rtl::OUString& rObjectCID,
    const uno::Reference< chart2::XChartDocument >& xChartDocument )
{
    ObjectType eType( ObjectIdentifier::getObjectType( rObjectCID ));
    Reference< frame::XModel > xModel( xChartDocument, uno::UNO_QUERY );

    switch( eType )
    {
        case OBJECTTYPE_AXIS:
            return getAxisName( rObjectCID, xModel );
        case OBJECTTYPE_TITLE:
            return getTitleName( rObjectCID, xModel );
        case OBJECTTYPE_GRID:
        case OBJECTTYPE_SUBGRID:
            return getGridName( rObjectCID, xModel );
        case OBJECTTYPE_DATA_SERIES:
            return lcl_getFullSeriesName( rObjectCID, xModel );
        //case OBJECTTYPE_LEGEND_ENTRY:
        case OBJECTTYPE_DATA_POINT:
        case OBJECTTYPE_DATA_LABELS:
        case OBJECTTYPE_DATA_LABEL:
        case OBJECTTYPE_DATA_ERRORS:
        case OBJECTTYPE_DATA_ERRORS_X:
        case OBJECTTYPE_DATA_ERRORS_Y:
        case OBJECTTYPE_DATA_ERRORS_Z:
        case OBJECTTYPE_DATA_CURVE:
        case OBJECTTYPE_DATA_AVERAGE_LINE:
        case OBJECTTYPE_DATA_CURVE_EQUATION:
            {
                rtl::OUString aRet = lcl_getFullSeriesName( rObjectCID, xModel );
                aRet += C2U(" ");
                if( eType == OBJECTTYPE_DATA_POINT || eType == OBJECTTYPE_DATA_LABEL )
                {
                    aRet += getName( OBJECTTYPE_DATA_POINT  );
                    sal_Int32 nPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID );
                    aRet += C2U(" ");
                    aRet += OUString::valueOf(nPointIndex+1);

                    if( eType == OBJECTTYPE_DATA_LABEL )
                    {
                        aRet += C2U(" ");
                        aRet += getName( OBJECTTYPE_DATA_LABEL  );
                    }
                }
                else
                    aRet += getName( eType );
                return aRet;
            }
        default:
            break;
    }

    return getName( eType );
}

rtl::OUString ObjectNameProvider::getName_ObjectForSeries(
        ObjectType eObjectType,
        const rtl::OUString& rSeriesCID,
        const uno::Reference< chart2::XChartDocument >& xChartDocument )
{
    uno::Reference< frame::XModel> xChartModel( xChartDocument, uno::UNO_QUERY );
    Reference< XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rSeriesCID , xChartModel ), uno::UNO_QUERY );
    if( xSeries.is() )
    {
        OUString aRet = String(SchResId(STR_OBJECT_FOR_SERIES));
        replaceParamterInString( aRet, C2U("%OBJECTNAME"), getName( eObjectType, false /*bPlural*/ ) );
        replaceParamterInString( aRet, C2U("%SERIESNAME"), lcl_getDataSeriesName( rSeriesCID, xChartModel ) );
        return aRet;
    }
    else
        return ObjectNameProvider::getName_ObjectForAllSeries( eObjectType );
}

rtl::OUString ObjectNameProvider::getName_ObjectForAllSeries( ObjectType eObjectType )
{
    OUString aRet = String(SchResId(STR_OBJECT_FOR_ALL_SERIES));
    replaceParamterInString( aRet, C2U("%OBJECTNAME"), getName( eObjectType, true /*bPlural*/ ) );
    return aRet;
}

//.............................................................................
} //namespace chart
//.............................................................................
