/**
 * @file TestProducer.cpp
 * @date May 3, 2010
 * @author ron
 *
 * @brief
 */

#include "TestData.h"
#include "../TestBase/TestBase.h"

/// @cond DOXYGEN_SKIP
SUITE( Data )
{
/// @endcond

	/**
	 * @struct ObservableFixture
	 * @brief Helper struct providing set-up/tear-down of Producer tests
	 *
	 * @copydetails EventFixture
	 */
	struct ProducerFixture
	{
		SuiteBase::SimulationTest sim;
		TestLogConsumer::Ptr log;
		ProducerTest producer;
		TypeInfo type;

		ProducerFixture()
		:	sim( "ProducerTestSim" )
		,	log( TestLogConsumer::create() )
		,	producer( sim, "ProducerTestFixtureProducer" )
		,	type( typeid(ProducerTest) )
		{
			sim.addConsumer( log );
		}
	};

	TEST_FIXTURE( ProducerFixture, Construction )
	{
		data::Label label = "ProducerTestConstruction";
		ProducerTest p( sim, label );

		CHECK_EQUAL( &sim,  &p.getSimulation() );
		CHECK_EQUAL( label, p.getLabel() );
		CHECK( type == p.getType() );
		CHECK( p.trace );
		CHECK( p.debug );
		CHECK( p.info );
		CHECK( p.warning );
		CHECK( p.error );
		CHECK( p.fatal );
		CHECK( p.statistics );

		CHECK_EQUAL( p.getSimulation().getChannel( channel_id::trace ), p.trace );
		CHECK_EQUAL( p.getSimulation().getChannel( channel_id::debug ), p.debug );
		CHECK_EQUAL( p.getSimulation().getChannel( channel_id::info ), p.info );
		CHECK_EQUAL( p.getSimulation().getChannel( channel_id::warning ), p.warning );
		CHECK_EQUAL( p.getSimulation().getChannel( channel_id::error ), p.error );
		CHECK_EQUAL( p.getSimulation().getChannel( channel_id::fatal ), p.fatal );
		CHECK_EQUAL( p.getSimulation().getChannel( channel_id::statistics ), p.statistics );
	}

	TEST_FIXTURE( ProducerFixture, DisableLogging )
	{
		producer.disableLogging();
		CHECK( ! producer.trace );
		CHECK( ! producer.debug );
		CHECK( ! producer.info );
		CHECK( producer.warning );
		CHECK( producer.error );
		CHECK( producer.fatal );
		CHECK( ! producer.statistics );
	}

	TEST_FIXTURE( ProducerFixture, EnableLogging )
	{
		producer.disableLogging();

		producer.enableLogging();
		CHECK( producer.trace );
		CHECK( producer.debug );
		CHECK( producer.info );
		CHECK( producer.warning );
		CHECK( producer.error );
		CHECK( producer.fatal );
		CHECK( producer.statistics );

		CHECK_EQUAL( producer.getSimulation().getChannel( channel_id::trace ), producer.trace );
		CHECK_EQUAL( producer.getSimulation().getChannel( channel_id::debug ), producer.debug );
		CHECK_EQUAL( producer.getSimulation().getChannel( channel_id::info ), producer.info );
		CHECK_EQUAL( producer.getSimulation().getChannel( channel_id::warning ), producer.warning );
		CHECK_EQUAL( producer.getSimulation().getChannel( channel_id::error ), producer.error );
		CHECK_EQUAL( producer.getSimulation().getChannel( channel_id::fatal ), producer.fatal );
		CHECK_EQUAL( producer.getSimulation().getChannel( channel_id::statistics ), producer.statistics );
	}

	TEST_FIXTURE( ProducerFixture, Log )
	{
		producer.trace << producer.log( "ProducerTestLog" );
		CHECK( log->getTraceRecord( "ProducerTestLog", TypeInfo() ) );

		base::SimTime time = 789;
		sim.setCurrentTime( time );
		StringLiteral msg = "ProducerTestLog";
		SimRecord record = producer.log( msg );
		CHECK_EQUAL( msg, record.getText() );
		CHECK_EQUAL( &producer, &record.getSender() );
		CHECK_EQUAL( &sim, &record.getSimulation() );
		CHECK_EQUAL( time, record.getTime() );
	}

	TEST_FIXTURE( ProducerFixture, Count )
	{
		SimRecord record = producer.count( "ProducerTestCount", 2 );
		CHECK_EQUAL( StringLiteral( "count" ), record.getText() );
		CHECK_EQUAL( StringLiteral( "ProducerTestCount" ), record.getDetails().front().first );
		CHECK_EQUAL( 2, record.getDetails().front().second.convert<int>() );
	}

	TEST_FIXTURE( ProducerFixture, Param )
	{
		SimRecord record = producer.param( "ProducerTestParam", "ParamValue" );
		CHECK_EQUAL( StringLiteral( "parameter" ), record.getText() );
		CHECK_EQUAL( StringLiteral( "ProducerTestParam" ), record.getDetails().front().first );
		CHECK_EQUAL( "ParamValue", record.getDetails().front().second.convert<std::string>() );
	}

	TEST_FIXTURE( ProducerFixture, Update )
	{
		SimRecord record = producer.update( "ProducerTestUpdate", 99.123 );
		CHECK_EQUAL( StringLiteral( "update" ), record.getText() );
		CHECK_EQUAL( StringLiteral( "ProducerTestUpdate" ), record.getDetails().front().first );
		CHECK_EQUAL( 99.123, record.getDetails().front().second.convert<double>() );
	}

	TEST_FIXTURE( ProducerFixture, Reset )
	{
		SimRecord record = producer.reset();
		CHECK_EQUAL( StringLiteral( "reset" ), record.getText() );
	}

	TEST_FIXTURE( ProducerFixture, StreamingOperator )
	{
		std::ostringstream os;
		os << producer;
		CHECK_EQUAL( producer.getLabel(), os.str() );

		os.str( "" );
		os << &producer;
		CHECK_EQUAL( producer.getLabel(), os.str() );
	}

/// @cond DOXYGEN_SKIP
}
/// @endcond
