/** \file
 *
 *  Contains the HFRadarModelCalc class declaration.
 *
 *  HFRadarModelCalc.h should only be included by HFRadarModelCalc.cpp
 *  Other classes should include HFRadarModelCalcIF.h
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */

#ifndef HFRADARMODELCALC_H_
#define HFRADARMODELCALC_H_

#include "component/SyncComponent.h"
#include "data/Mtx.h"

#include "estimationModule/HFRadarModelCalcIF.h"

class UniversalDataReader;
class UniversalDataWriter;

/**
 *  Over simplified HFRadarModelCalc component
 *
 *  HFRadarModelCalc.h should only be included by HFRadarModelCalc.cpp
 *  Other classes should include HFRadarModelCalcIF.h
 *
 *  Implements onboard models work.
 *
 *  \ingroup modules_estimation
 */
class HFRadarModelCalc : public SyncEstimationComponent
{
public:
    HFRadarModelCalc( const Module* module );
    virtual ~HFRadarModelCalc();

    /// Initialize function
    void initialize( void );

    /// The actual "payload" of the component
    void run();

    /// Return the singleton
    static HFRadarModelCalc* Instance()
    {
        return Instance_;
    }

    /// interpolate u & v at time dt seconds in the future from now,
    bool lookup( float& u, float& v, const double dt, const float latDeg, const float lonDeg );

    Timestamp getCalculationCompleteTime()
    {
        return calculationCompleteTime_;
    }

    /// returns the time_ member, units are epoch seconds.
    const double* getTime( int& timeSize )
    {
        timeSize = pHours_ + 1;
        return time_;
    }

    /// returns the size of the time_ member
    int getTimeSize()
    {
        return pHours_ + 1;
    }

    /// returns the lat_ member, units are radian.
    float* getLat( int& latSize )
    {
        latSize = gridY_.getM();
        return lat_;
    }

    /// returns the lon_ member, units are radian.
    float* getLon( int& lonSize )
    {
        lonSize = gridX_.getN();
        return lon_;
    }

    // returns the u_[time][lat][lon] member, units are m/s.
    float*** getU()
    {
        return u_;
    }

    // returns the v_[time][lat][lon] member, units are m/s.
    float*** getV()
    {
        return v_;
    }

    // returns the maxCurrent_ member, units are m/s.
    const float& getMaxCurrent()
    {
        return maxCurrent_;
    }


protected:

    Mtx glm2fwd( const Mtx& netImpMean, const Mtx& netTpca, const Mtx& netW1,
                 const Mtx& netB1, const Mtx& buf );

    void writeExpansionCoefficientsToSlate( void );

    void publishSurfaceCurrentAtVehicleLocation( void );

    const bool debug_;
    const Mtx eofs_;
    const Mtx ensMean_;
    const Mtx gridIdxRev_;
    const Mtx gridX_;
    const Mtx gridY_;
    const Mtx netB1_;
    const Mtx ulags_;
    const Mtx netImpMean_;
    const Mtx xlags_;
    const Mtx netTpca_;
    const Mtx netW1_;
    const Mtx stateInfoStdAll_;
    int dHours_; // # hours or real data
    int pHours_; // # hours to plan ahead
    Mtx gridIdx_;
    Mtx data_;
    Mtx st_;
    double* time_;
    double forecastEpochSeconds_[ HFRadarModelCalcIF::TOTAL_HOURS ];
    Timestamp forecastStartTime_;
    float* lat_;
    float* lon_;
    float*** u_;
    float*** v_;
    float maxCurrent_;
    bool ranOnce_;
    Timestamp calculationCompleteTime_;
    float velocityAccuracy_;

    UniversalDataReader* latitudeReader_;
    UniversalDataReader* longitudeReader_;
    UniversalDataReader* platformRommuniucationsReader_;

    BlobWriter* forecastExpansionCoefficientsWriter_;
    BlobWriter* forecastTimesWriter_;

    UniversalDataWriter* uWriter_;
    UniversalDataWriter* vWriter_;

    ConfigReader* velocityAccuracyConfigReader_;

    static HFRadarModelCalc* Instance_;

private:
    // Note that the copy constructor below is private and not given a body.
    // Any attempt to call it will return a compiler error.
    HFRadarModelCalc( const HFRadarModelCalc& old ); // disallow copy constructor

};

#endif /* HFRADARMODELCALC_H_ */
