/*
 *       File name:  libmetrics/psd.hh
 *         Project:  Aghermann
 *          Author:  Andrei Zavada <johnhommer@gmail.com>
 *
 * Initial version:  2010-04-28
 *
 *         Purpose:  CProfile and related stuff
 *
 *         License:  GPL
 */

#ifndef AGH_LIBMETRICS_PSD_H_
#define AGH_LIBMETRICS_PSD_H_

#include <string>
#include <list>
#include <valarray>

#include <fftw3.h>

#include "common/lang.hh"
#include "libsigproc/winfun.hh"
#include "forward-decls.hh"
#include "page-metrics-base.hh"

#if HAVE_CONFIG_H && !defined(VERSION)
#  include "config.h"
#endif

using namespace std;

namespace metrics {
namespace psd {


enum TFFTWPlanType {
        estimate,
        measure,
        TFFTWPlanType_total
};

inline int
plan_flags( TFFTWPlanType t)
{
        switch ( t ) {
        case TFFTWPlanType::estimate:
                return 0|FFTW_ESTIMATE;
        case TFFTWPlanType::measure:
                return 0|FFTW_MEASURE;
        default:
                return 0;
        }
}

inline TFFTWPlanType
plan_type( int f)
{
        // this is oversimplified
        if ( f & FFTW_MEASURE )
                return TFFTWPlanType::measure;
        if ( f & FFTW_ESTIMATE )
                return TFFTWPlanType::estimate;
        return (TFFTWPlanType)0;
}

struct SPPack
  : virtual public metrics::SPPack {
        double  binsize;
        sigproc::TWinType
                welch_window_type;
        TFFTWPlanType
                plan_type;

        SPPack ()
                {
                        sane_defaults();
                }

        SPPack (const SPPack& rv)
              : metrics::SPPack   (rv),
                binsize           (rv.binsize),
                welch_window_type (rv.welch_window_type),
                plan_type         (rv.plan_type)
                {}

        SPPack (const metrics::SPPack& base,
                const double binsize_,
                const sigproc::TWinType welch_window_type_, const TFFTWPlanType plan_type_)
              : metrics::SPPack   (base),
                binsize           (binsize_),
                welch_window_type (welch_window_type_),
                plan_type         (plan_type_)
                {}

        bool
        same_as( const SPPack& rv) const
                {
                        return  metrics::SPPack::same_as(rv) &&
                                agh::dbl_cmp( binsize, rv.binsize) == 0 &&
                                welch_window_type == rv.welch_window_type &&
                                plan_type         == rv.plan_type;
                }
        void
        make_same( const SPPack& rv)
                { metrics::SPPack::make_same(rv); }

        size_t
        compute_n_bins( size_t samplerate) const
                {
                        return (samplerate * pagesize + 1) / 2 / samplerate / binsize;
                }

        void
        check() const;

        void
        sane_defaults()
                {
                        metrics::SPPack::sane_defaults();
                        binsize = .25;
                        welch_window_type = sigproc::TWinType::hanning;
                        plan_type = TFFTWPlanType::measure;
                }

        const char*
        metric_name() const
                { return metrics::name( TType::psd); }
};





class CProfile
  : virtual public SPPack,
    virtual public metrics::CProfile {

    public:
        CProfile (const sigfile::CTypedSource&, int sig_no,
                  const SPPack&);

        // in a frequency range
        valarray<TFloat>
        course( const double from, const double upto) const
                {
                        valarray<TFloat> acc (0., steps());
                        size_t  bin_a = min( (size_t)(from / binsize), _bins),
                                bin_z = min( (size_t)(upto / binsize), _bins);
                        for ( size_t b = bin_a; b < bin_z; ++b )
                                acc += metrics::CProfile::course(b);
                        return move(acc);
                }

        int go_compute();
        string mirror_fname() const;

        string fname_base() const;

        int export_tsv( const string&) const;
        int export_tsv( float, float,
                        const string&) const;

        // // to enable use as mapped type
        // CProfile (const CProfile& rv)
        //       : SPPack (rv),
        //         metrics::CProfile (rv)
        //         {}
};

} // namespace psd
} // namespace metrics


#endif

// Local Variables:
// Mode: c++
// indent-tabs-mode: nil
// tab-width: 8
// c-basic-offset: 8
// End:
