/**************************************************************
 * 
 * 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 "StatisticsHelper.hxx"
#include "DataSeriesHelper.hxx"
#include "ErrorBar.hxx"
#include "macros.hxx"

#include <rtl/math.hxx>
#include <rtl/ustrbuf.hxx>
#include <comphelper/processfactory.hxx>

#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
#include <com/sun/star/chart2/data/XDataSink.hpp>
#include <com/sun/star/chart/ErrorBarStyle.hpp>

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

namespace
{

double lcl_getVariance( const Sequence< double > & rData, sal_Int32 & rOutValidCount,
        bool bUnbiasedEstimator )
{
    const sal_Int32 nCount = rData.getLength();
    rOutValidCount = nCount;

    double fSum = 0.0;
    double fQuadSum = 0.0;

    for( sal_Int32 i = 0; i < nCount; ++i )
    {
        const double fData = rData[i];
        if( ::rtl::math::isNan( fData ))
            --rOutValidCount;
        else
        {
            fSum     += fData;
            fQuadSum += fData * fData;
        }
    }

    double fResult;
    if( rOutValidCount == 0 )
        ::rtl::math::setNan( & fResult );
    else
    {
        const double fN = static_cast< double >( rOutValidCount );
        if( bUnbiasedEstimator )
            fResult = (fQuadSum - fSum*fSum/fN) / (fN - 1);
        else
            fResult = (fQuadSum - fSum*fSum/fN) / fN;
    }

    return fResult;
}

Reference< chart2::data::XLabeledDataSequence > lcl_getErrorBarLabeledSequence(
    const Reference< chart2::data::XDataSource > & xDataSource,
    bool bPositiveValue, bool bYError,
    OUString & rOutRoleNameUsed )
{
    OUStringBuffer aRole( C2U("error-bars-"));
    if( bYError )
        aRole.append( sal_Unicode( 'y' ));
    else
        aRole.append( sal_Unicode( 'x' ));

    OUString aPlainRole = aRole.makeStringAndClear();
    aRole.append( aPlainRole );
    aRole.append( sal_Unicode( '-' ));

    if( bPositiveValue )
        aRole = aRole.appendAscii( "positive" );
    else
        aRole = aRole.appendAscii( "negative" );

    OUString aLongRole = aRole.makeStringAndClear();
    Reference< chart2::data::XLabeledDataSequence > xLSeq(
        ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aLongRole ));
    // try role without "-negative" or "-positive" postfix
    if( xLSeq.is())
        rOutRoleNameUsed = aLongRole;
    else
    {
        xLSeq.set( ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aPlainRole ));
        if( xLSeq.is())
            rOutRoleNameUsed = aPlainRole;
        else
            rOutRoleNameUsed = aLongRole;
    }

    return xLSeq;
}

void lcl_setRole(
    const Reference< chart2::data::XDataSequence > & xNewSequence,
    const OUString & rRole )
{
    Reference< beans::XPropertySet > xSeqProp( xNewSequence, uno::UNO_QUERY );
    if( xSeqProp.is())
        xSeqProp->setPropertyValue( C2U("Role"), uno::makeAny( rRole ));
}

void lcl_addSequenceToDataSource(
    const Reference< chart2::data::XDataSource > & xDataSource,
    const Reference< chart2::data::XDataSequence > & xNewSequence,
    const OUString & rRole )
{
    Reference< chart2::data::XDataSink > xSink( xDataSource, uno::UNO_QUERY );
    Reference< lang::XMultiServiceFactory > xFact( comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
    if( ! ( xFact.is() && xSink.is() ))
        return;

    Reference< chart2::data::XLabeledDataSequence > xLSeq(
        xFact->createInstance( C2U("com.sun.star.chart2.data.LabeledDataSequence")), uno::UNO_QUERY );
    if( xLSeq.is())
    {
        lcl_setRole( xNewSequence, rRole );
        xLSeq->setValues( xNewSequence );
        Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
            xDataSource->getDataSequences());
        aSequences.realloc( aSequences.getLength() + 1 );
        aSequences[ aSequences.getLength() - 1 ] = xLSeq;
        xSink->setData( aSequences );
    }
}

void lcl_setXMLRangePropertyAtDataSequence(
    const Reference< chart2::data::XDataSequence > & xDataSequence,
    const OUString & rXMLRange )
{
    try
    {
        const OUString aXMLRangePropName( C2U( "CachedXMLRange" ));
        Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW );
        Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo());
        if( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ))
            xProp->setPropertyValue( aXMLRangePropName, uno::makeAny( rXMLRange ));
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }
}

} // anonymous namespace

namespace chart
{

double StatisticsHelper::getVariance(
    const Sequence< double > & rData,
    bool bUnbiasedEstimator /* = false */ )
{
    sal_Int32 nValCount;
    return lcl_getVariance( rData, nValCount, bUnbiasedEstimator );
}

double StatisticsHelper::getStandardDeviation( const Sequence< double > & rData )
{
    double fResult = getVariance( rData );
    if( ! ::rtl::math::isNan( fResult ))
        fResult = sqrt( fResult );

    return fResult;
}

double StatisticsHelper::getStandardError( const Sequence< double > & rData )
{
    sal_Int32 nValCount;
    double fVar = lcl_getVariance( rData, nValCount, false );
    double fResult;

    if( nValCount == 0 ||
        ::rtl::math::isNan( fVar ))
    {
        ::rtl::math::setNan( & fResult );
    }
    else
    {
        // standard-deviation / sqrt(n)
        fResult = sqrt( fVar ) / sqrt( double(nValCount) );
    }

    return fResult;
}

Reference< chart2::data::XLabeledDataSequence > StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
    const Reference< chart2::data::XDataSource > & xDataSource,
    bool bPositiveValue,
    bool bYError /* = true */ )
{
    Reference< chart2::data::XLabeledDataSequence > xResult;
    if( !xDataSource.is())
        return xResult;

    OUString aRole;
    Reference< chart2::data::XLabeledDataSequence > xLSeq(
        lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole ));
    if( xLSeq.is())
        xResult.set( xLSeq );

    return xResult;
}

Reference< chart2::data::XDataSequence > StatisticsHelper::getErrorDataSequenceFromDataSource(
    const Reference< chart2::data::XDataSource > & xDataSource,
    bool bPositiveValue,
    bool bYError /* = true */ )
{
    Reference< chart2::data::XLabeledDataSequence > xLSeq(
        StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
            xDataSource, bPositiveValue,
            bYError ));
    if( !xLSeq.is())
        return Reference< chart2::data::XDataSequence >();

    return xLSeq->getValues();
}

double StatisticsHelper::getErrorFromDataSource(
    const Reference< chart2::data::XDataSource > & xDataSource,
    sal_Int32 nIndex,
    bool bPositiveValue,
    bool bYError /* = true */ )
{
    double fResult = 0.0;
    ::rtl::math::setNan( & fResult );

    Reference< chart2::data::XDataSequence > xValues(
        StatisticsHelper::getErrorDataSequenceFromDataSource( xDataSource, bPositiveValue, bYError ));

    Reference< chart2::data::XNumericalDataSequence > xNumValues( xValues, uno::UNO_QUERY );
    if( xNumValues.is())
    {
        Sequence< double > aData( xNumValues->getNumericalData());
        if( nIndex < aData.getLength())
            fResult = aData[nIndex];
    }
    else if( xValues.is())
    {
        Sequence< uno::Any > aData( xValues->getData());
        if( nIndex < aData.getLength())
            aData[nIndex] >>= fResult;
    }

    return fResult;
}

void StatisticsHelper::setErrorDataSequence(
    const Reference< chart2::data::XDataSource > & xDataSource,
    const Reference< chart2::data::XDataProvider > & xDataProvider,
    const OUString & rNewRange,
    bool bPositiveValue,
    bool bYError /* = true */,
    OUString * pXMLRange /* = 0 */ )
{
    Reference< chart2::data::XDataSink > xDataSink( xDataSource, uno::UNO_QUERY );
    if( ! ( xDataSink.is() && xDataProvider.is()))
        return;

    OUString aRole;
    Reference< chart2::data::XLabeledDataSequence > xLSeq(
        lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole ));
    Reference< chart2::data::XDataSequence > xNewSequence(
        xDataProvider->createDataSequenceByRangeRepresentation( rNewRange ));
    if( xNewSequence.is())
    {
        if( pXMLRange )
            lcl_setXMLRangePropertyAtDataSequence( xNewSequence, *pXMLRange );
        if( xLSeq.is())
        {
            lcl_setRole( xNewSequence, aRole );
            xLSeq->setValues( xNewSequence );
        }
        else
            lcl_addSequenceToDataSource( xDataSource, xNewSequence, aRole );
    }
}

Reference< beans::XPropertySet > StatisticsHelper::addErrorBars(
    const Reference< chart2::XDataSeries > & xDataSeries,
    const Reference< uno::XComponentContext > & xContext,
    sal_Int32 nStyle,
    bool bYError /* = true */ )
{
    Reference< beans::XPropertySet > xErrorBar;
    Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY );
    if( !xSeriesProp.is())
        return xErrorBar;

    const OUString aPropName( bYError ? C2U("ErrorBarY") : C2U("ErrorBarX"));
    if( !( xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar ) ||
        !xErrorBar.is())
    {
        xErrorBar.set( createErrorBar( xContext ));
    }

    OSL_ASSERT( xErrorBar.is());
    if( xErrorBar.is())
    {
        xErrorBar->setPropertyValue( C2U("ErrorBarStyle"), uno::makeAny( nStyle ));
    }

    xSeriesProp->setPropertyValue( aPropName, uno::makeAny( xErrorBar ));

    return xErrorBar;
}

Reference< beans::XPropertySet > StatisticsHelper::getErrorBars(
    const Reference< chart2::XDataSeries > & xDataSeries,
    bool bYError /* = true */ )
{
    Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY );
    Reference< beans::XPropertySet > xErrorBar;
    const OUString aPropName( bYError ? C2U("ErrorBarY") : C2U("ErrorBarX"));

    if ( xSeriesProp.is())
        xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar;

    return xErrorBar;
}

bool StatisticsHelper::hasErrorBars(
    const Reference< chart2::XDataSeries > & xDataSeries,
    bool bYError /* = true */ )
{
    Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
    sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;

    return ( xErrorBar.is() &&
             ( xErrorBar->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) &&
             nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE );
}

void StatisticsHelper::removeErrorBars(
    const Reference< chart2::XDataSeries > & xDataSeries,
    bool bYError /* = true  */ )
{
    Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
    if ( xErrorBar.is())
        xErrorBar->setPropertyValue( C2U("ErrorBarStyle"), uno::makeAny(
                                         ::com::sun::star::chart::ErrorBarStyle::NONE ));
}

bool StatisticsHelper::usesErrorBarRanges(
    const Reference< chart2::XDataSeries > & xDataSeries,
    bool bYError /* = true */ )
{
    Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
    sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;

    return ( xErrorBar.is() &&
             ( xErrorBar->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) &&
             nStyle == ::com::sun::star::chart::ErrorBarStyle::FROM_DATA );
}

} //  namespace chart
