#include "gtest/gtest.h"

#include "RiaQDateTimeTools.h"
#include "RiaTimeHistoryCurveResampler.h"

//--------------------------------------------------------------------------------------------------
/// Constants
//--------------------------------------------------------------------------------------------------
static int SECS_PER_DAY = 60 * 60 * 24;

//--------------------------------------------------------------------------------------------------
/// Helpers
//--------------------------------------------------------------------------------------------------
static time_t toSecsSinceEpoch( const QString& timeString )
{
    return RiaQDateTimeTools::fromString( timeString, "yyyy-MM-dd" ).toSecsSinceEpoch();
}

static std::vector<time_t> toSecsSinceEpochVector( const std::vector<QString>& timeStrings )
{
    std::vector<time_t> tv;
    for ( auto& ts : timeStrings )
        tv.push_back( toSecsSinceEpoch( ts ) );
    return tv;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_Resampling_NoPeriod )
{
    std::vector<QString> timeStrings( { "2018-02-03", "2018-02-27" } );

    std::vector<double> dataValues( { 3.0, 5.0 } );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::MONTH );

    EXPECT_EQ( 1, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( toSecsSinceEpoch( "2018-03-01" ), resampler.resampledTimeSteps()[0] );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_Resampling_Decade )
{
    std::vector<QString> timeStrings( { "1989-02-03", "2005-06-06", "2012-02-07" } );

    std::vector<double> dataValues( { 0.0, 0.0, 0.0 } );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::DECADE );

    EXPECT_EQ( 4, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( toSecsSinceEpoch( "1990-01-01" ), resampler.resampledTimeSteps()[0] );
    EXPECT_EQ( toSecsSinceEpoch( "2000-01-01" ), resampler.resampledTimeSteps()[1] );
    EXPECT_EQ( toSecsSinceEpoch( "2010-01-01" ), resampler.resampledTimeSteps()[2] );
    EXPECT_EQ( toSecsSinceEpoch( "2020-01-01" ), resampler.resampledTimeSteps()[3] );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_Resampling_Year )
{
    std::vector<QString> timeStrings( { "2014-06-06", "2015-12-02", "2018-02-07" } );

    std::vector<double> dataValues( { 0.0, 0.0, 0.0 } );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::YEAR );

    EXPECT_EQ( 5, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( toSecsSinceEpoch( "2015-01-01" ), resampler.resampledTimeSteps()[0] );
    EXPECT_EQ( toSecsSinceEpoch( "2016-01-01" ), resampler.resampledTimeSteps()[1] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-01-01" ), resampler.resampledTimeSteps()[2] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-01-01" ), resampler.resampledTimeSteps()[3] );
    EXPECT_EQ( toSecsSinceEpoch( "2019-01-01" ), resampler.resampledTimeSteps()[4] );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_Resampling_HalfYear )
{
    std::vector<QString> timeStrings( { "2016-06-06", "2017-03-02", "2018-02-07" } );

    std::vector<double> dataValues( { 0.0, 0.0, 0.0 } );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::HALFYEAR );

    EXPECT_EQ( 5, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( toSecsSinceEpoch( "2016-07-01" ), resampler.resampledTimeSteps()[0] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-01-01" ), resampler.resampledTimeSteps()[1] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-07-01" ), resampler.resampledTimeSteps()[2] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-01-01" ), resampler.resampledTimeSteps()[3] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-07-01" ), resampler.resampledTimeSteps()[4] );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_Resampling_Quarter )
{
    std::vector<QString> timeStrings( { "2016-09-06", "2017-03-02", "2018-02-07" } );

    std::vector<double> dataValues( { 0.0, 0.0, 0.0 } );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::QUARTER );

    EXPECT_EQ( 7, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( toSecsSinceEpoch( "2016-10-01" ), resampler.resampledTimeSteps()[0] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-01-01" ), resampler.resampledTimeSteps()[1] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-04-01" ), resampler.resampledTimeSteps()[2] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-07-01" ), resampler.resampledTimeSteps()[3] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-10-01" ), resampler.resampledTimeSteps()[4] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-01-01" ), resampler.resampledTimeSteps()[5] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-04-01" ), resampler.resampledTimeSteps()[6] );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_Resampling_Month )
{
    std::vector<QString> timeStrings( { "2017-09-06", "2017-12-02", "2018-02-07" } );

    std::vector<double> dataValues( { 0.0, 0.0, 0.0 } );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::MONTH );

    EXPECT_EQ( 6, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( toSecsSinceEpoch( "2017-10-01" ), resampler.resampledTimeSteps()[0] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-11-01" ), resampler.resampledTimeSteps()[1] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-12-01" ), resampler.resampledTimeSteps()[2] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-01-01" ), resampler.resampledTimeSteps()[3] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-02-01" ), resampler.resampledTimeSteps()[4] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-03-01" ), resampler.resampledTimeSteps()[5] );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_Resampling_Week )
{
    std::vector<QString> timeStrings( { "2017-11-02", "2017-12-24", "2018-01-07" } );

    std::vector<double> dataValues( { 0.0, 0.0, 0.0 } );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::WEEK );

    EXPECT_EQ( 10, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( toSecsSinceEpoch( "2017-11-06" ), resampler.resampledTimeSteps()[0] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-11-13" ), resampler.resampledTimeSteps()[1] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-11-20" ), resampler.resampledTimeSteps()[2] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-11-27" ), resampler.resampledTimeSteps()[3] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-12-04" ), resampler.resampledTimeSteps()[4] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-12-11" ), resampler.resampledTimeSteps()[5] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-12-18" ), resampler.resampledTimeSteps()[6] );
    EXPECT_EQ( toSecsSinceEpoch( "2017-12-25" ), resampler.resampledTimeSteps()[7] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-01-01" ), resampler.resampledTimeSteps()[8] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-01-08" ), resampler.resampledTimeSteps()[9] );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_Resampling_NoSampleCrossingPeriodBoundary )
{
    std::vector<QString> timeStrings( { "2017-01-02", "2017-06-15", "2017-12-24" } );

    std::vector<double> dataValues( { 0.0, 0.0, 0.0 } );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::YEAR );

    EXPECT_EQ( 1, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( toSecsSinceEpoch( "2018-01-01" ), resampler.resampledTimeSteps()[0] );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_WeightedMean_SingleSample )
{
    std::vector<QString> timeStrings( { "2018-02-07" } );

    std::vector<double> dataValues( { 3.0 } );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::MONTH );

    EXPECT_EQ( 1, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( toSecsSinceEpoch( "2018-03-01" ), resampler.resampledTimeSteps()[0] );

    double value = 0.0;
    EXPECT_NEAR( value, resampler.resampledValues()[0], 1e-12 );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_WeightedMean_Days )
{
    std::vector<QString> timeStrings( { "2018-02-03", "2018-02-07" } );

    std::vector<double> dataValues( { 3.0, 5.0 } );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::DAY );

    EXPECT_EQ( 5, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( toSecsSinceEpoch( "2018-02-03" ), resampler.resampledTimeSteps()[0] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-02-04" ), resampler.resampledTimeSteps()[1] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-02-05" ), resampler.resampledTimeSteps()[2] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-02-06" ), resampler.resampledTimeSteps()[3] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-02-07" ), resampler.resampledTimeSteps()[4] );

    EXPECT_NEAR( 3.0, resampler.resampledValues()[0], 1e-12 );
    EXPECT_NEAR( 5.0, resampler.resampledValues()[1], 1e-12 );
    EXPECT_NEAR( 5.0, resampler.resampledValues()[2], 1e-12 );
    EXPECT_NEAR( 5.0, resampler.resampledValues()[3], 1e-12 );
    EXPECT_NEAR( 5.0, resampler.resampledValues()[4], 1e-12 );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_WeightedMean_Decade )
{
    std::vector<QString> timeStrings( { "1999-02-03", "2005-06-06", "2012-02-07" } );

    std::vector<double> dataValues( { 3.0, 5.0, 7.0 } );

    time_t t0  = toSecsSinceEpoch( "1999-02-03" );
    time_t t1  = toSecsSinceEpoch( "2005-06-06" );
    time_t t2  = toSecsSinceEpoch( "2012-02-07" );
    time_t tp0 = toSecsSinceEpoch( "2000-01-01" );
    time_t tp1 = toSecsSinceEpoch( "2010-01-01" );
    time_t tp2 = toSecsSinceEpoch( "2020-01-01" );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::DECADE );

    EXPECT_EQ( 3, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( tp0, resampler.resampledTimeSteps()[0] );
    EXPECT_EQ( tp1, resampler.resampledTimeSteps()[1] );
    EXPECT_EQ( tp2, resampler.resampledTimeSteps()[2] );

    double value0 = 5.0 * ( tp0 - t0 ) / ( tp0 - toSecsSinceEpoch( "1990-01-01" ) );
    double value1 = ( 5.0 * ( t1 - tp0 ) + 7.0 * ( tp1 - t1 ) ) / ( tp1 - tp0 );
    double value2 = 7.0 * ( t2 - tp1 ) / ( tp2 - tp1 );

    EXPECT_NEAR( value0, resampler.resampledValues()[0], 1e-12 );
    EXPECT_NEAR( value1, resampler.resampledValues()[1], 1e-12 );
    EXPECT_NEAR( value2, resampler.resampledValues()[2], 1e-12 );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_WeightedMean_SamplesStartBeforePeriod )
{
    std::vector<QString> timeStrings( { "2018-01-20", "2018-01-29", "2018-02-03", "2018-02-27", "2018-03-02" } );

    std::vector<double> dataValues( { 3.0, 5.0, 7.0, 11.0, 13.0 } );

    time_t tp0 = toSecsSinceEpoch( "2018-02-01" );
    time_t tp1 = toSecsSinceEpoch( "2018-03-01" );
    time_t tp2 = toSecsSinceEpoch( "2018-04-01" );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::MONTH );

    EXPECT_EQ( 3, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( tp0, resampler.resampledTimeSteps()[0] );
    EXPECT_EQ( tp1, resampler.resampledTimeSteps()[1] );
    EXPECT_EQ( tp2, resampler.resampledTimeSteps()[2] );

    double value0 = ( 5.0 * 9 + 7.0 * 3 ) * SECS_PER_DAY / ( tp0 - toSecsSinceEpoch( "2018-01-01" ) );

    double value1 = ( 7.0 * 2 + 11.0 * 24 + 13.0 * 2 ) * SECS_PER_DAY / ( tp1 - tp0 );

    double value2 = 13.0 * 1 * SECS_PER_DAY / ( tp2 - tp1 );

    EXPECT_NEAR( value0, resampler.resampledValues()[0], 1e-12 );
    EXPECT_NEAR( value1, resampler.resampledValues()[1], 1e-12 );
    EXPECT_NEAR( value2, resampler.resampledValues()[2], 1e-12 );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_WeightedMean_SamplesStartBeforePeriod_TimeStepsMatchPeriod )
{
    std::vector<QString> timeStrings( { "2018-01-20", "2018-02-01", "2018-02-03", "2018-03-01", "2018-03-02" } );

    std::vector<double> dataValues( { 3.0, 5.0, 7.0, 11.0, 13.0 } );

    time_t tp0 = toSecsSinceEpoch( "2018-02-01" );
    time_t tp1 = toSecsSinceEpoch( "2018-03-01" );
    time_t tp2 = toSecsSinceEpoch( "2018-04-01" );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::MONTH );

    EXPECT_EQ( 3, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( tp0, resampler.resampledTimeSteps()[0] );
    EXPECT_EQ( tp1, resampler.resampledTimeSteps()[1] );
    EXPECT_EQ( tp2, resampler.resampledTimeSteps()[2] );

    double value0 = ( 5.0 * 12 ) * SECS_PER_DAY / ( tp0 - toSecsSinceEpoch( "2018-01-01" ) );

    double value1 = ( 7.0 * 2 + 11.0 * 26 ) * SECS_PER_DAY / ( tp1 - tp0 );

    double value2 = 13.0 * 1 * SECS_PER_DAY / ( tp2 - tp1 );

    EXPECT_NEAR( value0, resampler.resampledValues()[0], 1e-12 );
    EXPECT_NEAR( value1, resampler.resampledValues()[1], 1e-12 );
    EXPECT_NEAR( value2, resampler.resampledValues()[2], 1e-12 );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_WeightedMean_SamplesStartAndEndMatchPeriod )
{
    std::vector<QString> timeStrings( { "2018-02-01", "2018-02-10", "2018-03-01" } );

    std::vector<double> dataValues( { 3.0, 5.0, 7.0 } );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::MONTH );

    EXPECT_EQ( 2, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( toSecsSinceEpoch( "2018-02-01" ), resampler.resampledTimeSteps().front() );
    EXPECT_EQ( toSecsSinceEpoch( "2018-03-01" ), resampler.resampledTimeSteps().back() );

    time_t timePeriod = toSecsSinceEpoch( "2018-03-01" ) - toSecsSinceEpoch( "2018-02-01" );

    double value1 = 3.0;
    double value2 = ( 5.0 * 9 + 7.0 * 19 ) * SECS_PER_DAY / timePeriod;

    EXPECT_NEAR( value1, resampler.resampledValues()[0], 1e-12 );
    EXPECT_NEAR( value2, resampler.resampledValues()[1], 1e-12 );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_WeightedMean_SamplesStartMatchPeriodStart )
{
    std::vector<QString> timeStrings( { "2018-02-01", "2018-02-10", "2018-03-01", "2018-03-02" } );

    std::vector<double> dataValues( { 3.0, 5.0, 7.0, 11.0 } );

    time_t tp0 = toSecsSinceEpoch( "2018-02-01" );
    time_t tp1 = toSecsSinceEpoch( "2018-03-01" );
    time_t tp2 = toSecsSinceEpoch( "2018-04-01" );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::MONTH );

    EXPECT_EQ( 3, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( tp0, resampler.resampledTimeSteps()[0] );
    EXPECT_EQ( tp1, resampler.resampledTimeSteps()[1] );
    EXPECT_EQ( tp2, resampler.resampledTimeSteps()[2] );

    double value0 = 3.0;
    double value1 = ( 5.0 * 9 + 7.0 * 19 ) * SECS_PER_DAY / ( tp1 - tp0 );
    double value2 = 11.0 * 1 * SECS_PER_DAY / ( tp2 - tp1 );

    EXPECT_NEAR( value0, resampler.resampledValues()[0], 1e-12 );
    EXPECT_NEAR( value1, resampler.resampledValues()[1], 1e-12 );
    EXPECT_NEAR( value2, resampler.resampledValues()[2], 1e-12 );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_WeightedMean_MultipleSamplesInLastPeriod )
{
    std::vector<QString> timeStrings( { "2018-02-10", "2018-03-02", "2018-03-05", "2018-03-15" } );

    std::vector<double> dataValues( { 3.0, 5.0, 7.0, 11.0 } );

    time_t tp0 = toSecsSinceEpoch( "2018-03-01" );
    time_t tp1 = toSecsSinceEpoch( "2018-04-01" );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputeWeightedMeanValues( RiaDefines::DateTimePeriod::MONTH );

    EXPECT_EQ( 2, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( tp0, resampler.resampledTimeSteps()[0] );
    EXPECT_EQ( tp1, resampler.resampledTimeSteps()[1] );

    double value0 = 5.0 * 19 * SECS_PER_DAY / ( tp0 - toSecsSinceEpoch( "2018-02-01" ) );
    double value1 = ( 0.0 * 17 + 11.0 * 10 + 7.0 * 3 + 5.0 * 1 ) * SECS_PER_DAY / ( tp1 - tp0 );

    EXPECT_NEAR( value0, resampler.resampledValues()[0], 1e-12 );
    EXPECT_NEAR( value1, resampler.resampledValues()[1], 1e-12 );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_PeriodEndValues_SingleSample )
{
    std::vector<QString> timeStrings( { "2018-02-10" } );

    std::vector<double> dataValues( { 3.0 } );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputePeriodEndValues( RiaDefines::DateTimePeriod::MONTH );

    EXPECT_EQ( 1, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( toSecsSinceEpoch( "2018-03-01" ), resampler.resampledTimeSteps()[0] );

    EXPECT_NEAR( 3.0, resampler.resampledValues()[0], 1e-12 );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_PeriodEndValues_SamplesStartBeforePeriod )
{
    std::vector<QString> timeStrings( { "2018-01-30", "2018-02-10", "2018-03-05", "2018-03-02" } );

    std::vector<double> dataValues( { 3.0, 5.0, 7.0, 11.0 } );

    time_t t0  = toSecsSinceEpoch( "2018-01-30" );
    time_t t1  = toSecsSinceEpoch( "2018-02-10" );
    time_t t2  = toSecsSinceEpoch( "2018-03-05" );
    time_t tp0 = toSecsSinceEpoch( "2018-02-01" );
    time_t tp1 = toSecsSinceEpoch( "2018-03-01" );
    time_t tp2 = toSecsSinceEpoch( "2018-04-01" );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputePeriodEndValues( RiaDefines::DateTimePeriod::MONTH );

    EXPECT_EQ( 3, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( tp0, resampler.resampledTimeSteps()[0] );
    EXPECT_EQ( tp1, resampler.resampledTimeSteps()[1] );
    EXPECT_EQ( tp2, resampler.resampledTimeSteps()[2] );

    double value0 = ( 5.0 - 3.0 ) * ( tp0 - t0 ) / ( t1 - t0 ) + 3.0;
    double value1 = ( 7.0 - 5.0 ) * ( tp1 - t1 ) / ( t2 - t1 ) + 5.0;
    double value2 = 11.0;

    EXPECT_NEAR( value0, resampler.resampledValues()[0], 1e-12 );
    EXPECT_NEAR( value1, resampler.resampledValues()[1], 1e-12 );
    EXPECT_NEAR( value2, resampler.resampledValues()[2], 1e-12 );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_PeriodEndValues_SamplesStartMatchPeriod )
{
    std::vector<QString> timeStrings( { "2018-02-01", "2018-02-10", "2018-03-01", "2018-03-02" } );

    std::vector<double> dataValues( { 3.0, 5.0, 7.0, 11.0 } );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputePeriodEndValues( RiaDefines::DateTimePeriod::MONTH );

    EXPECT_EQ( 3, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( toSecsSinceEpoch( "2018-02-01" ), resampler.resampledTimeSteps()[0] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-03-01" ), resampler.resampledTimeSteps()[1] );
    EXPECT_EQ( toSecsSinceEpoch( "2018-04-01" ), resampler.resampledTimeSteps()[2] );

    EXPECT_NEAR( 3.0, resampler.resampledValues()[0], 1e-12 );
    EXPECT_NEAR( 7.0, resampler.resampledValues()[1], 1e-12 );
    EXPECT_NEAR( 11.0, resampler.resampledValues()[2], 1e-12 );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveResampler, Test_PeriodEndValues_SamplesStartAndEndMatchPeriod )
{
    std::vector<QString> timeStrings( { "2018-02-01", "2018-02-10", "2018-03-01" } );

    std::vector<double> dataValues( { 3.0, 5.0, 7.0 } );

    RiaTimeHistoryCurveResampler resampler;
    resampler.setCurveData( dataValues, toSecsSinceEpochVector( timeStrings ) );
    resampler.resampleAndComputePeriodEndValues( RiaDefines::DateTimePeriod::MONTH );

    EXPECT_EQ( 2, (int)resampler.resampledTimeSteps().size() );
    EXPECT_EQ( toSecsSinceEpoch( "2018-02-01" ), resampler.resampledTimeSteps().front() );
    EXPECT_EQ( toSecsSinceEpoch( "2018-03-01" ), resampler.resampledTimeSteps().back() );

    EXPECT_NEAR( 3.0, resampler.resampledValues()[0], 1e-12 );
    EXPECT_NEAR( 7.0, resampler.resampledValues()[1], 1e-12 );
}
