/**************************************************************
 * 
 * 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 "DataBrowserModel.hxx"
#include "DialogModel.hxx"
#include "ChartModelHelper.hxx"
#include "DiagramHelper.hxx"
#include "DataSeriesHelper.hxx"
#include "PropertyHelper.hxx"
#include "ControllerLockGuard.hxx"
#include "macros.hxx"
#include "StatisticsHelper.hxx"
#include "ContainerHelper.hxx"
#include "ChartTypeHelper.hxx"
#include "chartview/ExplicitValueProvider.hxx"
#include "ExplicitCategoriesProvider.hxx"

#include <com/sun/star/container/XIndexReplace.hpp>
#include <com/sun/star/chart2/XAxis.hpp>
#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
#include <com/sun/star/chart2/XInternalDataProvider.hpp>
#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
#include <com/sun/star/chart2/XChartTypeContainer.hpp>
#include <com/sun/star/chart2/data/XDataSource.hpp>
#include <com/sun/star/chart2/data/XDataSink.hpp>
#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
#include <com/sun/star/util/XModifiable.hpp>

#include <rtl/math.hxx>

#include <algorithm>

#if OSL_DEBUG_LEVEL > 1
#include <cstdio>
#endif

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

using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::rtl::OUString;

namespace
{
OUString lcl_getRole(
    const Reference< chart2::data::XDataSequence > & xSeq )
{
    OUString aResult;
    Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
    if( xProp.is())
    {
        try
        {
            xProp->getPropertyValue( C2U("Role")) >>= aResult;
        }
        catch( const uno::Exception & ex )
        {
            ASSERT_EXCEPTION( ex );
        }
    }
    return aResult;
}


OUString lcl_getRole(
    const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
{
    OUString aResult;
    if( xLSeq.is())
        aResult = lcl_getRole( xLSeq->getValues());
    return aResult;
}

OUString lcl_getUIRoleName(
    const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
{
    OUString aResult( lcl_getRole( xLSeq ));
    if( aResult.getLength())
        aResult = ::chart::DialogModel::ConvertRoleFromInternalToUI( aResult );
    return aResult;
}

void lcl_copyDataSequenceProperties(
    const Reference< chart2::data::XDataSequence > & xOldSequence,
    const Reference< chart2::data::XDataSequence > & xNewSequence )
{
    Reference< beans::XPropertySet > xOldSeqProp( xOldSequence, uno::UNO_QUERY );
    Reference< beans::XPropertySet > xNewSeqProp( xNewSequence, uno::UNO_QUERY );
    comphelper::copyProperties( xOldSeqProp, xNewSeqProp );
}

bool lcl_SequenceOfSeriesIsShared(
    const Reference< chart2::XDataSeries > & xSeries,
    const Reference< chart2::data::XDataSequence > & xValues )
{
    bool bResult = false;
    if( !xValues.is())
        return bResult;
    try
    {
        OUString aValuesRole( lcl_getRole( xValues ));
        OUString aValuesRep( xValues->getSourceRangeRepresentation());
        Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW );
        Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeq( xSource->getDataSequences());
        for( sal_Int32 i=0; i<aLSeq.getLength(); ++i )
            if( aLSeq[i].is() &&
                lcl_getRole( aLSeq[i] ).equals( aValuesRole ))
            {
                // getValues().is(), because lcl_getRole checked that already
                bResult = (aValuesRep == aLSeq[i]->getValues()->getSourceRangeRepresentation());
                // assumption: a role appears only once in a series
                break;
            }
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }
    return bResult;
}

typedef ::std::vector< Reference< chart2::data::XLabeledDataSequence > > lcl_tSharedSeqVec;

lcl_tSharedSeqVec lcl_getSharedSequences( const Sequence< Reference< chart2::XDataSeries > > & rSeries )
{
    // @todo: if only some series share a sequence, those have to be duplicated
    // and made unshared for all series
    lcl_tSharedSeqVec aResult;
    // if we have only one series, we don't want any shared sequences
    if( rSeries.getLength() <= 1 )
        return aResult;

    Reference< chart2::data::XDataSource > xSource( rSeries[0], uno::UNO_QUERY );
    Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeq( xSource->getDataSequences());
    for( sal_Int32 nIdx=0; nIdx<aLSeq.getLength(); ++nIdx )
    {
        Reference< chart2::data::XDataSequence > xValues( aLSeq[nIdx]->getValues());
        bool bShared = true;
        for( sal_Int32 nSeriesIdx=1; nSeriesIdx<rSeries.getLength(); ++nSeriesIdx )
        {
            bShared = lcl_SequenceOfSeriesIsShared( rSeries[nSeriesIdx], xValues );
            if( !bShared )
                break;
        }
        if( bShared )
            aResult.push_back( aLSeq[nIdx] );
    }

    return aResult;
}

sal_Int32 lcl_getValuesRepresentationIndex(
    const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
{
    sal_Int32 nResult = -1;
    if( xLSeq.is())
    {
        Reference< chart2::data::XDataSequence > xSeq( xLSeq->getValues());
        if( xSeq.is())
        {
            OUString aRep( xSeq->getSourceRangeRepresentation());
            nResult = aRep.toInt32();
        }
    }
    return nResult;
}

struct lcl_RepresentationsOfLSeqMatch : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
{
    lcl_RepresentationsOfLSeqMatch( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) :
            m_aValuesRep( xLSeq.is() ?
                          (xLSeq->getValues().is() ? xLSeq->getValues()->getSourceRangeRepresentation() : OUString())
                          : OUString() )
    {}
    bool operator() ( const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
    {
        return (xLSeq.is() &&
                xLSeq->getValues().is() &&
                (xLSeq->getValues()->getSourceRangeRepresentation() == m_aValuesRep ));
    }
private:
    OUString m_aValuesRep;
};

struct lcl_RolesOfLSeqMatch : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
{
    lcl_RolesOfLSeqMatch( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) :
            m_aRole( lcl_getRole( xLSeq ))
    {}
    bool operator() ( const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
    {
        return lcl_getRole( xLSeq ).equals( m_aRole );
    }
private:
    OUString m_aRole;
};

bool lcl_ShowCategories( const Reference< chart2::XDiagram > & /* xDiagram */ )
{
    // show categories for all charts
    return true;
//     return DiagramHelper::isCategoryDiagram( xDiagram );
}

bool lcl_ShowCategoriesAsDataLabel( const Reference< chart2::XDiagram > & xDiagram )
{
    return ! ::chart::DiagramHelper::isCategoryDiagram( xDiagram );
}

} // anonymous namespace

namespace chart
{


struct DataBrowserModel::tDataColumn
{
    ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDataSeries >                m_xDataSeries;
    sal_Int32                                                  m_nIndexInDataSeries;
    ::rtl::OUString                                            m_aUIRoleName;
    ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::data::XLabeledDataSequence > m_xLabeledDataSequence;
    eCellType                                                  m_eCellType;
    sal_Int32                                                  m_nNumberFormatKey;

    // default CTOR
    tDataColumn() : m_nIndexInDataSeries( -1 ), m_eCellType( TEXT ), m_nNumberFormatKey( 0 ) {}
    // "full" CTOR
    tDataColumn(
        const ::com::sun::star::uno::Reference<
        ::com::sun::star::chart2::XDataSeries > & xDataSeries,
        sal_Int32 nIndexInDataSeries,
        ::rtl::OUString aUIRoleName,
        ::com::sun::star::uno::Reference<
        ::com::sun::star::chart2::data::XLabeledDataSequence >  xLabeledDataSequence,
        eCellType aCellType,
        sal_Int32 nNumberFormatKey ) :
            m_xDataSeries( xDataSeries ),
            m_nIndexInDataSeries( nIndexInDataSeries ),
            m_aUIRoleName( aUIRoleName ),
            m_xLabeledDataSequence( xLabeledDataSequence ),
            m_eCellType( aCellType ),
            m_nNumberFormatKey( nNumberFormatKey )
    {}
};

struct DataBrowserModel::implColumnLess : public ::std::binary_function<
        DataBrowserModel::tDataColumn, DataBrowserModel::tDataColumn, bool >
{
    bool operator() ( const first_argument_type & rLeft, const second_argument_type & rRight )
    {
        if( rLeft.m_xLabeledDataSequence.is() && rRight.m_xLabeledDataSequence.is())
        {
            return DialogModel::GetRoleIndexForSorting( lcl_getRole( rLeft.m_xLabeledDataSequence )) <
                DialogModel::GetRoleIndexForSorting( lcl_getRole( rRight.m_xLabeledDataSequence ));
        }
        return true;
    }
};

DataBrowserModel::DataBrowserModel(
    const Reference< chart2::XChartDocument > & xChartDoc,
    const Reference< uno::XComponentContext > & xContext ) :
        m_xChartDocument( xChartDoc ),
        m_xContext( xContext ),
        m_apDialogModel( new DialogModel( xChartDoc, xContext ))
{
    updateFromModel();
}

DataBrowserModel::~DataBrowserModel()
{}

namespace
{
struct lcl_DataSeriesOfHeaderMatches : public ::std::unary_function< ::chart::DataBrowserModel::tDataHeader, bool >
{
    lcl_DataSeriesOfHeaderMatches(
        const Reference< chart2::XDataSeries > & xSeriesToCompareWith ) :
            m_xSeries( xSeriesToCompareWith )
    {}
    bool operator() ( const ::chart::DataBrowserModel::tDataHeader & rHeader )
    {
        return (m_xSeries == rHeader.m_xDataSeries);
    }
private:
    Reference< chart2::XDataSeries  > m_xSeries;
};
}

void DataBrowserModel::insertDataSeries( sal_Int32 nAfterColumnIndex )
{
    OSL_ASSERT( m_apDialogModel.get());
    Reference< chart2::XInternalDataProvider > xDataProvider(
        m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
    if( xDataProvider.is())
    {
        if( isCategoriesColumn(nAfterColumnIndex) )
            nAfterColumnIndex = getCategoryColumnCount()-1;

        sal_Int32 nStartCol = 0;
        Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartDocument ));
        Reference< chart2::XChartType > xChartType;
        Reference< chart2::XDataSeries > xSeries;
        if( static_cast< tDataColumnVector::size_type >( nAfterColumnIndex ) <= m_aColumns.size())
            xSeries.set( m_aColumns[nAfterColumnIndex].m_xDataSeries );

        sal_Int32 nSeriesNumberFormat = 0;
        if( xSeries.is())
        {
            xChartType.set( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries ));
            tDataHeaderVector::const_iterator aIt(
                ::std::find_if( m_aHeaders.begin(), m_aHeaders.end(),
                                lcl_DataSeriesOfHeaderMatches( xSeries )));
            if( aIt != m_aHeaders.end())
                nStartCol = aIt->m_nEndColumn;

            Reference< beans::XPropertySet > xSeriesProps( xSeries, uno::UNO_QUERY );
            if( xSeriesProps.is() )
                xSeriesProps->getPropertyValue( C2U( "NumberFormat" )) >>= nSeriesNumberFormat;
        }
        else
        {
            xChartType.set( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ));
            nStartCol = nAfterColumnIndex;
        }

        if( xChartType.is())
        {
            sal_Int32 nOffset = 0;
            if( xDiagram.is() && lcl_ShowCategories( xDiagram ))
                nOffset=getCategoryColumnCount();
            // get shared sequences of current series
            Reference< chart2::XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY );
            lcl_tSharedSeqVec aSharedSequences;
            if( xSeriesCnt.is())
                aSharedSequences = lcl_getSharedSequences( xSeriesCnt->getDataSeries());
            Reference< chart2::XDataSeries > xNewSeries(
                m_apDialogModel->insertSeriesAfter( xSeries, xChartType, true /* bCreateDataCachedSequences */ ));
            if( xNewSeries.is())
            {
                {
                    Reference< chart2::data::XDataSource > xSource( xNewSeries, uno::UNO_QUERY );
                    if( xSource.is())
                    {
                        Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSequences(
                            xSource->getDataSequences());
                        sal_Int32 nSeqIdx = 0;
                        sal_Int32 nSeqSize = aLSequences.getLength();
                        nStartCol -= (nOffset - 1);
                        for( sal_Int32 nIndex = nStartCol;
                             (nSeqIdx < nSeqSize);
                             ++nSeqIdx )
                        {
                            lcl_tSharedSeqVec::const_iterator aSharedIt(
                                ::std::find_if( aSharedSequences.begin(), aSharedSequences.end(),
                                                lcl_RolesOfLSeqMatch( aLSequences[nSeqIdx] )));
                            if( aSharedIt != aSharedSequences.end())
                            {
                                aLSequences[nSeqIdx]->setValues( (*aSharedIt)->getValues());
                                aLSequences[nSeqIdx]->setLabel( (*aSharedIt)->getLabel());
                            }
                            else
                            {
                                xDataProvider->insertSequence( nIndex - 1 );

                                // values
                                Reference< chart2::data::XDataSequence > xNewSeq(
                                    xDataProvider->createDataSequenceByRangeRepresentation(
                                        OUString::valueOf( nIndex )));
                                lcl_copyDataSequenceProperties(
                                    aLSequences[nSeqIdx]->getValues(), xNewSeq );
                                aLSequences[nSeqIdx]->setValues( xNewSeq );

                                // labels
                                Reference< chart2::data::XDataSequence > xNewLabelSeq(
                                    xDataProvider->createDataSequenceByRangeRepresentation(
                                        OUString( RTL_CONSTASCII_USTRINGPARAM( "label " )) +
                                        OUString::valueOf( nIndex )));
                                lcl_copyDataSequenceProperties(
                                    aLSequences[nSeqIdx]->getLabel(), xNewLabelSeq );
                                aLSequences[nSeqIdx]->setLabel( xNewLabelSeq );
                                ++nIndex;
                            }
                        }
                    }
                }
                if( nSeriesNumberFormat != 0 )
                {
                    //give the new series the same number format as the former series especially for bubble charts thus the bubble size values can be edited with same format immidiately
                    Reference< beans::XPropertySet > xNewSeriesProps( xNewSeries, uno::UNO_QUERY );
                    if( xNewSeriesProps.is() )
                        xNewSeriesProps->setPropertyValue( C2U( "NumberFormat" ), uno::makeAny( nSeriesNumberFormat ) );
                }

                updateFromModel();
            }
        }
    }
}

void DataBrowserModel::insertComplexCategoryLevel( sal_Int32 nAfterColumnIndex )
{
    //create a new text column for complex categories

    OSL_ASSERT( m_apDialogModel.get());
    Reference< chart2::XInternalDataProvider > xDataProvider( m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
    if( xDataProvider.is() )
    {
        if( !isCategoriesColumn(nAfterColumnIndex) )
            nAfterColumnIndex = getCategoryColumnCount()-1;

        if(nAfterColumnIndex<0)
        {
            OSL_ENSURE( false, "wrong index for category level insertion" );
            return;
        }

        m_apDialogModel->startControllerLockTimer();
        ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
        xDataProvider->insertComplexCategoryLevel( nAfterColumnIndex+1 );
        updateFromModel();
    }
}

void DataBrowserModel::removeDataSeriesOrComplexCategoryLevel( sal_Int32 nAtColumnIndex )
{
    OSL_ASSERT( m_apDialogModel.get());
    if( static_cast< tDataColumnVector::size_type >( nAtColumnIndex ) < m_aColumns.size())
    {
        Reference< chart2::XDataSeries > xSeries( m_aColumns[nAtColumnIndex].m_xDataSeries );
        if( xSeries.is())
        {
            m_apDialogModel->deleteSeries(
                xSeries, getHeaderForSeries( xSeries ).m_xChartType );

            //delete sequences from internal data provider that are not used anymore
            //but do not delete sequences that are still in use by the remaining series
            Reference< chart2::XInternalDataProvider > xDataProvider( m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
            Reference< chart2::data::XDataSource > xSourceOfDeletedSeries( xSeries, uno::UNO_QUERY );
            if( xDataProvider.is() && xSourceOfDeletedSeries.is())
            {
                ::std::vector< sal_Int32 > aSequenceIndexesToDelete;
                Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequencesOfDeletedSeries( xSourceOfDeletedSeries->getDataSequences() );
                Reference< chart2::XDataSeriesContainer > xSeriesCnt( getHeaderForSeries( xSeries ).m_xChartType, uno::UNO_QUERY );
                if( xSeriesCnt.is())
                {
                    Reference< chart2::data::XDataSource > xRemainingDataSource( DataSeriesHelper::getDataSource( xSeriesCnt->getDataSeries() ) );
                    if( xRemainingDataSource.is() )
                    {
                        ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aRemainingSeq( ContainerHelper::SequenceToVector( xRemainingDataSource->getDataSequences() ) );
                        for( sal_Int32 i=0; i<aSequencesOfDeletedSeries.getLength(); ++i )
                        {
                            ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::const_iterator aHitIt(
                                ::std::find_if( aRemainingSeq.begin(), aRemainingSeq.end(),
                                    lcl_RepresentationsOfLSeqMatch( aSequencesOfDeletedSeries[i] )));
                            // if not used by the remaining series this sequence can be deleted
                            if( aHitIt == aRemainingSeq.end() )
                                aSequenceIndexesToDelete.push_back( lcl_getValuesRepresentationIndex( aSequencesOfDeletedSeries[i] ) );
                        }
                    }
                }

                // delete unnecessary sequences of the internal data
                // iterate using greatest index first, so that deletion does not
                // shift other sequences that will be deleted later
                ::std::sort( aSequenceIndexesToDelete.begin(), aSequenceIndexesToDelete.end());
                for( ::std::vector< sal_Int32 >::reverse_iterator aIt(
                         aSequenceIndexesToDelete.rbegin()); aIt != aSequenceIndexesToDelete.rend(); ++aIt )
                {
                    if( *aIt != -1 )
                        xDataProvider->deleteSequence( *aIt );
                }
            }
            updateFromModel();
        }
        else
        {
            //delete a category column if there is more than one level (in case of a single column we do not get here)
            OSL_ENSURE(nAtColumnIndex>0, "wrong index for categories deletion" );

            Reference< chart2::XInternalDataProvider > xDataProvider( m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
            if( xDataProvider.is() )
            {
                m_apDialogModel->startControllerLockTimer();
                ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
                xDataProvider->deleteComplexCategoryLevel( nAtColumnIndex );
                updateFromModel();
            }
        }
    }
}

void DataBrowserModel::swapDataSeries( sal_Int32 nFirstColumnIndex )
{
    OSL_ASSERT( m_apDialogModel.get());
    if( static_cast< tDataColumnVector::size_type >( nFirstColumnIndex ) < m_aColumns.size() - 1 )
    {
        Reference< chart2::XDataSeries > xSeries( m_aColumns[nFirstColumnIndex].m_xDataSeries );
        if( xSeries.is())
        {
            m_apDialogModel->moveSeries( xSeries, DialogModel::MOVE_DOWN );
            updateFromModel();
        }
    }
}

void DataBrowserModel::swapDataPointForAllSeries( sal_Int32 nFirstIndex )
{
    OSL_ASSERT( m_apDialogModel.get());
    Reference< chart2::XInternalDataProvider > xDataProvider(
        m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
    // lockControllers
    ControllerLockGuard aGuard( m_apDialogModel->getChartModel());
    if( xDataProvider.is())
        xDataProvider->swapDataPointWithNextOneForAllSequences( nFirstIndex );
    // unlockControllers
}

void DataBrowserModel::insertDataPointForAllSeries( sal_Int32 nAfterIndex )
{
    Reference< chart2::XInternalDataProvider > xDataProvider(
        m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
    // lockControllers
    ControllerLockGuard aGuard( m_apDialogModel->getChartModel());
    if( xDataProvider.is())
        xDataProvider->insertDataPointForAllSequences( nAfterIndex );
    // unlockControllers
}

void DataBrowserModel::removeDataPointForAllSeries( sal_Int32 nAtIndex )
{
    Reference< chart2::XInternalDataProvider > xDataProvider(
        m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
    // lockControllers
    ControllerLockGuard aGuard( m_apDialogModel->getChartModel());
    if( xDataProvider.is())
        xDataProvider->deleteDataPointForAllSequences( nAtIndex );
    // unlockControllers
}

DataBrowserModel::tDataHeader DataBrowserModel::getHeaderForSeries(
    const Reference< chart2::XDataSeries > & xSeries ) const
{
    for( tDataHeaderVector::const_iterator aIt( m_aHeaders.begin());
         aIt != m_aHeaders.end(); ++aIt )
    {
        if( aIt->m_xDataSeries == xSeries )
            return (*aIt);
    }
    return tDataHeader();
}

Reference< chart2::XDataSeries >
    DataBrowserModel::getDataSeriesByColumn( sal_Int32 nColumn ) const
{
    tDataColumnVector::size_type nIndex( nColumn );
    if( nIndex < m_aColumns.size())
        return m_aColumns[nIndex].m_xDataSeries;
    return 0;
}

DataBrowserModel::eCellType DataBrowserModel::getCellType( sal_Int32 nAtColumn, sal_Int32 /* nAtRow */ ) const
{
    eCellType eResult = TEXT;
    tDataColumnVector::size_type nIndex( nAtColumn );
    if( nIndex < m_aColumns.size())
        eResult = m_aColumns[nIndex].m_eCellType;
    return eResult;
}

double DataBrowserModel::getCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow )
{
    double fResult;
    ::rtl::math::setNan( & fResult );

    tDataColumnVector::size_type nIndex( nAtColumn );
    if( nIndex < m_aColumns.size() &&
        m_aColumns[ nIndex ].m_xLabeledDataSequence.is())
    {
        Reference< chart2::data::XNumericalDataSequence > xData(
            m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY );
        if( xData.is())
        {
            Sequence< double > aValues( xData->getNumericalData());
            if( nAtRow < aValues.getLength())
                fResult = aValues[nAtRow];
        }
    }
    return fResult;
}

uno::Any DataBrowserModel::getCellAny( sal_Int32 nAtColumn, sal_Int32 nAtRow )
{
    uno::Any aResult;

    tDataColumnVector::size_type nIndex( nAtColumn );
    if( nIndex < m_aColumns.size() &&
        m_aColumns[ nIndex ].m_xLabeledDataSequence.is())
    {
        Reference< chart2::data::XDataSequence > xData(
            m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues() );
        if( xData.is() )
        {
            Sequence< uno::Any > aValues( xData->getData());
            if( nAtRow < aValues.getLength())
                aResult = aValues[nAtRow];
        }
    }
    return aResult;
}

OUString DataBrowserModel::getCellText( sal_Int32 nAtColumn, sal_Int32 nAtRow )
{
    OUString aResult;

    tDataColumnVector::size_type nIndex( nAtColumn );
    if( nIndex < m_aColumns.size() &&
        m_aColumns[ nIndex ].m_xLabeledDataSequence.is())
    {
        Reference< chart2::data::XTextualDataSequence > xData(
            m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY );
        if( xData.is())
        {
            Sequence< OUString > aValues( xData->getTextualData());
            if( nAtRow < aValues.getLength())
                aResult = aValues[nAtRow];
        }
    }
    return aResult;
}

sal_uInt32 DataBrowserModel::getNumberFormatKey( sal_Int32 nAtColumn, sal_Int32 /* nAtRow */ )
{
    tDataColumnVector::size_type nIndex( nAtColumn );
    if( nIndex < m_aColumns.size())
        return m_aColumns[ nIndex ].m_nNumberFormatKey;
    return 0;
}

bool DataBrowserModel::setCellAny( sal_Int32 nAtColumn, sal_Int32 nAtRow, const uno::Any & rValue )
{
    bool bResult = false;
    tDataColumnVector::size_type nIndex( nAtColumn );
    if( nIndex < m_aColumns.size() &&
        m_aColumns[ nIndex ].m_xLabeledDataSequence.is())
    {
        bResult = true;
        try
        {
            ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );

            // label
            if( nAtRow == -1 )
            {
                Reference< container::XIndexReplace > xIndexReplace(
                    m_aColumns[ nIndex ].m_xLabeledDataSequence->getLabel(), uno::UNO_QUERY_THROW );
                xIndexReplace->replaceByIndex( 0, rValue );
            }
            else
            {
                Reference< container::XIndexReplace > xIndexReplace(
                    m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY_THROW );
                xIndexReplace->replaceByIndex( nAtRow, rValue );
            }

            m_apDialogModel->startControllerLockTimer();
            //notify change directly to the model (this is necessary here as sequences for complex categories not known directly to the chart model so they do not notify their changes) (for complex categories see issue #i82971#)
            Reference< util::XModifiable > xModifiable( m_xChartDocument, uno::UNO_QUERY );
            if( xModifiable.is() )
                xModifiable->setModified(true);
        }
        catch( const uno::Exception & ex )
        {
            (void)(ex);
            bResult = false;
        }
    }
    return bResult;
}

bool DataBrowserModel::setCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow, double fValue )
{
    return (getCellType( nAtColumn, nAtRow ) == NUMBER) &&
        setCellAny( nAtColumn, nAtRow, uno::makeAny( fValue ));
}

bool DataBrowserModel::setCellText( sal_Int32 nAtColumn, sal_Int32 nAtRow, const ::rtl::OUString & rText )
{
    return (getCellType( nAtColumn, nAtRow ) == TEXT) &&
        setCellAny( nAtColumn, nAtRow, uno::makeAny( rText ));
}

sal_Int32 DataBrowserModel::getColumnCount() const
{
    return static_cast< sal_Int32 >( m_aColumns.size());
}

sal_Int32 DataBrowserModel::getMaxRowCount() const
{
    sal_Int32 nResult = 0;
    tDataColumnVector::const_iterator aIt( m_aColumns.begin());
    for( ; aIt != m_aColumns.end(); ++aIt )
    {
        if( aIt->m_xLabeledDataSequence.is())
        {
            Reference< chart2::data::XDataSequence > xSeq(
                aIt->m_xLabeledDataSequence->getValues());
            if( !xSeq.is())
                continue;
            sal_Int32 nLength( xSeq->getData().getLength());
            if( nLength > nResult )
                nResult = nLength;
        }
    }

    return nResult;
}

OUString DataBrowserModel::getRoleOfColumn( sal_Int32 nColumnIndex ) const
{
    if( nColumnIndex != -1 &&
        static_cast< sal_uInt32 >( nColumnIndex ) < m_aColumns.size())
        return m_aColumns[ nColumnIndex ].m_aUIRoleName;
    return OUString();
}

bool DataBrowserModel::isCategoriesColumn( sal_Int32 nColumnIndex ) const
{
    bool bIsCategories = false;
    if( nColumnIndex>=0 && nColumnIndex<static_cast< sal_Int32 >(m_aColumns.size()) )
        bIsCategories = !m_aColumns[ nColumnIndex ].m_xDataSeries.is();
    return bIsCategories;
}

sal_Int32 DataBrowserModel::getCategoryColumnCount()
{
    sal_Int32 nLastTextColumnIndex = -1;
    tDataColumnVector::const_iterator aIt = m_aColumns.begin();
    for( ; aIt != m_aColumns.end(); ++aIt )
    {
        if( !aIt->m_xDataSeries.is() )
            nLastTextColumnIndex++;
        else
            break;
    }
    return nLastTextColumnIndex+1;
}

const DataBrowserModel::tDataHeaderVector& DataBrowserModel::getDataHeaders() const
{
    return m_aHeaders;
}

void DataBrowserModel::updateFromModel()
{
    if( !m_xChartDocument.is())
        return;
    m_aColumns.clear();
    m_aHeaders.clear();

    Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartDocument ));
    if( !xDiagram.is())
        return;

    // set template at DialogModel
    uno::Reference< lang::XMultiServiceFactory > xFact( m_xChartDocument->getChartTypeManager(), uno::UNO_QUERY );
    DiagramHelper::tTemplateWithServiceName aTemplateAndService =
        DiagramHelper::getTemplateForDiagram( xDiagram, xFact );
    if( aTemplateAndService.first.is())
        m_apDialogModel->setTemplate( aTemplateAndService.first );

    sal_Int32 nHeaderStart = 0;
    sal_Int32 nHeaderEnd   = 0;
    if( lcl_ShowCategories( xDiagram ))
    {
        Reference< frame::XModel > xChartModel( m_xChartDocument, uno::UNO_QUERY );
        ExplicitCategoriesProvider aExplicitCategoriesProvider( ChartModelHelper::getFirstCoordinateSystem(xChartModel), xChartModel );

        const Sequence< Reference< chart2::data::XLabeledDataSequence> >& rSplitCategoriesList( aExplicitCategoriesProvider.getSplitCategoriesList() );
        sal_Int32 nLevelCount = rSplitCategoriesList.getLength();
        for( sal_Int32 nL = 0; nL<nLevelCount; nL++ )
        {
            Reference< chart2::data::XLabeledDataSequence > xCategories( rSplitCategoriesList[nL] );
            if( !xCategories.is() )
                continue;

            tDataColumn aCategories;
            aCategories.m_xLabeledDataSequence.set( xCategories );
            if( lcl_ShowCategoriesAsDataLabel( xDiagram ))
                aCategories.m_aUIRoleName = DialogModel::GetRoleDataLabel();
            else
                aCategories.m_aUIRoleName = lcl_getUIRoleName( xCategories );
            aCategories.m_eCellType = TEXTORDATE;
            m_aColumns.push_back( aCategories );
            ++nHeaderStart;
        }
    }

    Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY );
    if( !xCooSysCnt.is())
        return;
    Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
    for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
    {
        Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
        Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
        sal_Int32 nXAxisNumberFormat = DataSeriesHelper::getNumberFormatKeyFromAxis( 0, aCooSysSeq[nCooSysIdx], 0, 0 );

        for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
        {
            Reference< chart2::XDataSeriesContainer > xSeriesCnt( aChartTypes[nCTIdx], uno::UNO_QUERY );
            if( xSeriesCnt.is())
            {
                rtl::OUString aRoleForDataLabelNumberFormat = ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( aChartTypes[nCTIdx] );

                Sequence< Reference< chart2::XDataSeries > > aSeries( xSeriesCnt->getDataSeries());
                lcl_tSharedSeqVec aSharedSequences( lcl_getSharedSequences( aSeries ));
                for( lcl_tSharedSeqVec::const_iterator aIt( aSharedSequences.begin());
                     aIt != aSharedSequences.end(); ++aIt )
                {
                    tDataColumn aSharedSequence;
                    aSharedSequence.m_xLabeledDataSequence = *aIt;
                    aSharedSequence.m_aUIRoleName = lcl_getUIRoleName( *aIt );
                    aSharedSequence.m_eCellType = NUMBER;
                    // as the sequences are shared it should be ok to take the first series
                    // @todo: dimension index 0 for x-values used here. This is just a guess.
                    // Also, the axis index is 0, as there is usually only one x-axis
                    aSharedSequence.m_nNumberFormatKey = nXAxisNumberFormat;
                    m_aColumns.push_back( aSharedSequence );
                    ++nHeaderStart;
                }
                for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeries.getLength(); ++nSeriesIdx )
                {
                    tDataColumnVector::size_type nStartColIndex = m_aColumns.size();
                    Reference< chart2::XDataSeries > xSeries( aSeries[nSeriesIdx] );
                    Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
                    if( xSource.is())
                    {
                        Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeqs( xSource->getDataSequences());
                        if( aLSeqs.getLength() == 0 )
                            continue;
                        nHeaderEnd = nHeaderStart;

                        // @todo: dimension index 1 for y-values used here. This is just a guess
                        sal_Int32 nYAxisNumberFormatKey =
                            DataSeriesHelper::getNumberFormatKeyFromAxis(
                                aSeries[nSeriesIdx], aCooSysSeq[nCooSysIdx], 1 );

                        sal_Int32 nSeqIdx=0;
                        for( ; nSeqIdx<aLSeqs.getLength(); ++nSeqIdx )
                        {
                            sal_Int32 nSequenceNumberFormatKey = nYAxisNumberFormatKey;
                            OUString aRole = lcl_getRole( aLSeqs[nSeqIdx] );

                            if( aRole.equals( aRoleForDataLabelNumberFormat ) )
                            {
                                nSequenceNumberFormatKey = ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel(
                                    Reference< beans::XPropertySet >( xSeries, uno::UNO_QUERY ), xSeries, -1, xDiagram );
                            }
                            else if( aRole.equals( C2U( "values-x" ) ) )
                                nSequenceNumberFormatKey = nXAxisNumberFormat;
                            
                            if( ::std::find_if( aSharedSequences.begin(), aSharedSequences.end(),
                                             lcl_RepresentationsOfLSeqMatch( aLSeqs[nSeqIdx] )) == aSharedSequences.end())
                            {
                                // no shared sequence
                                m_aColumns.push_back(
                                    tDataColumn(
                                        aSeries[nSeriesIdx],
                                        nSeqIdx,
                                        lcl_getUIRoleName( aLSeqs[nSeqIdx] ),
                                        aLSeqs[nSeqIdx],
                                        NUMBER,
                                        nSequenceNumberFormatKey ));
                                ++nHeaderEnd;
                            }
                            // else skip
                        }
                        bool bSwapXAndYAxis = false;
                        try
                        {
                            Reference< beans::XPropertySet > xProp( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY );
                            xProp->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("SwapXAndYAxis"))) >>= bSwapXAndYAxis;
                        }
                        catch( const beans::UnknownPropertyException & ex )
                        {
                            (void)ex;
                        }

                        // add ranges for error bars if present for a series
                        if( StatisticsHelper::usesErrorBarRanges( aSeries[nSeriesIdx], /* bYError = */ true ))
                            addErrorBarRanges( aSeries[nSeriesIdx], nYAxisNumberFormatKey, nSeqIdx, nHeaderEnd );

                        m_aHeaders.push_back(
                            tDataHeader(
                                aSeries[nSeriesIdx],
                                aChartTypes[nCTIdx],
                                bSwapXAndYAxis,
                                nHeaderStart,
                                nHeaderEnd - 1 ));

                        nHeaderStart = nHeaderEnd;

                        ::std::sort( m_aColumns.begin() + nStartColIndex, m_aColumns.end(), implColumnLess() );
                    }
                }
            }
        }
    }
}

void DataBrowserModel::addErrorBarRanges(
    const Reference< chart2::XDataSeries > & xDataSeries,
    sal_Int32 nNumberFormatKey,
    sal_Int32 & rInOutSequenceIndex,
    sal_Int32 & rInOutHeaderEnd )
{
    try
    {
        ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aSequences;

        // x error bars
        // ------------
        Reference< chart2::data::XDataSource > xErrorSource(
            StatisticsHelper::getErrorBars( xDataSeries, /* bYError = */ false ), uno::UNO_QUERY );

        // positive x error bars
        Reference< chart2::data::XLabeledDataSequence > xErrorLSequence(
            StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
                xErrorSource,
                /* bPositiveValue = */ true,
                /* bYError = */ false ));
        if( xErrorLSequence.is())
            aSequences.push_back( xErrorLSequence );

        // negative x error bars
        xErrorLSequence.set(
            StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
                xErrorSource,
                /* bPositiveValue = */ false,
                /* bYError = */ false ));
        if( xErrorLSequence.is())
            aSequences.push_back( xErrorLSequence );

        // y error bars
        // ------------
        xErrorSource.set(
            StatisticsHelper::getErrorBars( xDataSeries, /* bYError = */ true ), uno::UNO_QUERY );

        // positive y error bars
        xErrorLSequence.set(
            StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
                xErrorSource,
                /* bPositiveValue = */ true,
                /* bYError = */ true ));
        if( xErrorLSequence.is())
            aSequences.push_back( xErrorLSequence );

        // negative y error bars
        xErrorLSequence.set(
            StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
                xErrorSource,
                /* bPositiveValue = */ false,
                /* bYError = */ true ));
        if( xErrorLSequence.is())
            aSequences.push_back( xErrorLSequence );


        for( ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::const_iterator aIt( aSequences.begin());
             aIt != aSequences.end(); ++aIt )
        {
            m_aColumns.push_back(
                tDataColumn(
                    xDataSeries,
                    rInOutSequenceIndex,
                    lcl_getUIRoleName( *aIt ),
                    *aIt,
                    NUMBER,
                    nNumberFormatKey ));
            ++rInOutSequenceIndex;
            ++rInOutHeaderEnd;
        }
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }
}

} //  namespace chart
