/** \file
 *
 *  Contains the DepAvgTempFrontDetector class implementation.
 *
 *  follows the template of StratificationFrontDetector.
 *
 *  Copyright (c) 2013, 2014 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */

#include "DepAvgTempFrontDetector.h"
#include "DepAvgTempFrontDetectorIF.h"
#include "derivationModule/TempGradientCalculatorIF.h"

#include "data/ConfigReader.h" // TODO: Shouldn't have to explicitly include this in each component.

DepAvgTempFrontDetector::DepAvgTempFrontDetector( const Module* module )
    : SyncEstimationComponent( DepAvgTempFrontDetectorIF::NAME, module ),
      verbosity_( 0 ),
      dataTimestamp_( Timestamp::NOT_SET_TIME ),
      value_( nanf( "" ) ),
      tempHoriGradThreshold_( 2.0 ),
      cntThreshold_( 5 ),
      countColdToWarm_( 0 ),
      countWarmToCold_( 0 ),
      coldToWarm_( false ),
      warmToCold_( false ),
      flagLogColdToWarm_( false ),
      flagLogWarmToCold_( false ),
      verbosityLevelConfigReader_( newConfigReader( DepAvgTempFrontDetectorIF::VERBOSITY ) ),
      tempHoriGradThresholdConfigReader_( newConfigReader( DepAvgTempFrontDetectorIF::TEMP_HORI_GRAD_THRESHOLD ) ),
      cntThresholdConfigReader_( newConfigReader( DepAvgTempFrontDetectorIF::CNT_TEMP_HORI_GRAD_THRESHOLD ) ),
      valueReader_( newDataReader( TempGradientCalculatorIF::TEMP_HORI_GRAD ) ),
      countColdToWarmWriter_( newDataWriter( DepAvgTempFrontDetectorIF::COUNT_COLD_TO_WARM ) ),
      countWarmToColdWriter_( newDataWriter( DepAvgTempFrontDetectorIF::COUNT_WARM_TO_COLD ) ),
      depAvgTempFrontWriter_( newDataWriter( DepAvgTempFrontDetectorIF::DEPAVG_TEMP_FRONT ) ),
      coldToWarmWriter_( newDataWriter( DepAvgTempFrontDetectorIF::COLD_TO_WARM ) ),
      warmToColdWriter_( newDataWriter( DepAvgTempFrontDetectorIF::WARM_TO_COLD ) )
{
    readConfig();
}

DepAvgTempFrontDetector::~DepAvgTempFrontDetector()
{}

void DepAvgTempFrontDetector::readConfig( void )
{
    verbosityLevelConfigReader_->read( Units::COUNT, verbosity_ );
    tempHoriGradThresholdConfigReader_->read( Units::CELSIUS, tempHoriGradThreshold_ );
    cntThresholdConfigReader_->read( Units::COUNT, cntThreshold_ );
}

void DepAvgTempFrontDetector::run( void )
{
    readConfig();
    if( readData() )
    {
        if( value_ >= tempHoriGradThreshold_ )
            countColdToWarm_++;
        else
        {
            countColdToWarm_ = 0;
            coldToWarm_ = false;
            flagLogColdToWarm_ = false;
        }

        if( value_ <= -tempHoriGradThreshold_ )
            countWarmToCold_++;
        else
        {
            countWarmToCold_ = 0;
            warmToCold_ = false;
            flagLogWarmToCold_ = false;
        }

        writeData();

        if( countColdToWarm_ >= cntThreshold_ )
        {
            //debug
            //printf("tempHoriGradThreshold_, cntThreshold_, countColdToWarm_, countWarmToCold_ = \n%f, %d, %d, %d\n\n", tempHoriGradThreshold_, cntThreshold_, countColdToWarm_, countWarmToCold_);

            if( !flagLogColdToWarm_ )
            {
                logger_.syslog( "Detected cold-to-warm front!", ( verbosity_ > 1 ) ? Syslog::IMPORTANT : Syslog::INFO );
                flagLogColdToWarm_ = true;
                coldToWarm_ = true;
            }

            logger_.syslog( "countColdToWarm_ = " + Str( countColdToWarm_ ), Syslog::INFO );

        }

        if( countWarmToCold_ >= cntThreshold_ )
        {
            //debug
            //printf("tempHoriGradThreshold_, cntThreshold_, countColdToWarm_, countWarmToCold_ = \n%f, %d, %d, %d\n\n", tempHoriGradThreshold_, cntThreshold_, countColdToWarm_, countWarmToCold_);

            if( !flagLogWarmToCold_ )
            {
                logger_.syslog( "Detected warm-to-cold front!", ( verbosity_ > 1 ) ? Syslog::IMPORTANT : Syslog::INFO );
                flagLogWarmToCold_ = true;
                warmToCold_ = true;
            }

            logger_.syslog( "countWarmToCold_ = " + Str( countWarmToCold_ ), Syslog::INFO );

        }

    }
}

bool DepAvgTempFrontDetector::readData( void )
{
    if( valueReader_->isActive() && valueReader_->wasTouchedSinceLastRun( this ) )
    {
        return valueReader_->read( Units::CELSIUS, value_ );
    }
    return false;
}

void DepAvgTempFrontDetector::writeData( void )
{
    countColdToWarmWriter_->write( Units::COUNT, countColdToWarm_, dataTimestamp_ );
    countWarmToColdWriter_->write( Units::COUNT, countWarmToCold_, dataTimestamp_ );
    depAvgTempFrontWriter_->write( Units::BOOL, ( ( countColdToWarm_ >= cntThreshold_ ) || ( countWarmToCold_ >= cntThreshold_ ) ), dataTimestamp_ );
    coldToWarmWriter_->write( Units::BOOL, coldToWarm_, dataTimestamp_ );
    warmToColdWriter_->write( Units::BOOL, warmToCold_, dataTimestamp_ );
}
