/*
 *       File name:  aghermann/artifact-detection/3in1.hh
 *         Project:  Aghermann
 *          Author:  Andrei Zavada <johnhommer@gmail.com>
 * Initial version:  2013-10-14
 *
 *         Purpose:  Comprehensive artifact detection
 *
 *         License:  GPL
 */

#ifndef AGH_AGHERMANN_ARTIFACT_DETECTION_3IN1_H_
#define AGH_AGHERMANN_ARTIFACT_DETECTION_3IN1_H_

#include <list>

#include <gtk/gtk.h>

#include "common/lang.hh"
#include "libsigfile/typed-source.hh"
#include "libmetrics/mc-artifacts.hh"
#include "aghermann/expdesign/dirlevel.hh"
#include "aghermann/expdesign/forward-decls.hh"

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

using namespace std;

namespace agh {
namespace ad {

struct SComprehensiveArtifactDetectionPPack {
        // one
        bool    do_flat_regions;
        double  flat_min_size,
                flat_pad;

        // two
        bool    do_emg_perturbations;
        size_t  emg_steady_secs;
        double  emg_max_dev_factor;
        double  emg_min_steadytone_factor,
                emg_min_steadytone_run;

        // three
        bool    do_mc_based;
        metrics::mc::SArtifactDetectionPPack
                MC;

        bool
        operator==( const SComprehensiveArtifactDetectionPPack& rv) const
                {
                        return  do_flat_regions      == rv.do_flat_regions &&
                                do_emg_perturbations == rv.do_emg_perturbations &&
                                do_mc_based          == rv.do_mc_based &&
                                dbl_cmp( flat_min_size, rv.flat_min_size)  == 0 &&
                                dbl_cmp( flat_pad, rv.flat_pad)            == 0 &&
                                dbl_cmp( emg_steady_secs, rv.emg_steady_secs)       == 0 &&
                                dbl_cmp( emg_max_dev_factor, rv.emg_max_dev_factor) == 0 &&
                                dbl_cmp( emg_min_steadytone_factor, rv.emg_min_steadytone_factor) == 0 &&
                                dbl_cmp( emg_min_steadytone_run, rv.emg_min_steadytone_run)       == 0 &&
                                MC == rv.MC;
                }
};


inline
void
make_default_SComprehensiveArtifactDetectionPPack( SComprehensiveArtifactDetectionPPack& A)
{
        A.do_flat_regions = A.do_emg_perturbations = A.do_mc_based = true;
        A.flat_min_size             = .5;
        A.flat_pad                  = .5;
        A.emg_steady_secs           = 10;
        A.emg_max_dev_factor        = 1.1;
        A.emg_min_steadytone_factor = 1.2;
        A.emg_min_steadytone_run    = 2.;
        metrics::mc::make_default_SArtifactDetectionPPack( A.MC);
}


class CComprehensiveArtifactDetector
  : public agh::CStorablePPack {

    public:
        static constexpr const char* common_subdir = ".artifact-profiles/";

        CComprehensiveArtifactDetector (const string& name_, agh::TExpDirLevel, agh::CExpDesign&, const agh::SExpDirLevelId&);
        CComprehensiveArtifactDetector (agh::CExpDesign& ED_, const agh::SExpDirLevelId& level_id_)
              : CStorablePPack (common_subdir, "(unnamed)", agh::TExpDirLevel::transient, ED_, level_id_)
                {
                        make_default_SComprehensiveArtifactDetectionPPack( Pp);
                }
        explicit CComprehensiveArtifactDetector (const CComprehensiveArtifactDetector& rv)
              : CStorablePPack (rv),
                Pp (rv.Pp)
                {}
        explicit CComprehensiveArtifactDetector (CComprehensiveArtifactDetector&& rv)
              : CStorablePPack (common_subdir, move(rv.name), rv.level, rv.ED, move(rv.level_id)),
                Pp (move(rv.Pp))
                {
                        rv.level = agh::TExpDirLevel::transient;
                }

       ~CComprehensiveArtifactDetector ()
                {
                        save();
                }

        CComprehensiveArtifactDetector&
        operator=( const CComprehensiveArtifactDetector& rv)
                { return Pp = rv.Pp, *this; }

        bool
        operator==( const CComprehensiveArtifactDetector& rv) const
                { return Pp == rv.Pp; }  // don't bother about CStorable

        string serialize() const;

        SComprehensiveArtifactDetectionPPack
                Pp;
};



enum class TDetectArtifactsResult {
        marked_nothing,
        marked_same,
        marked_new,
};

TDetectArtifactsResult
detect_artifacts( sigfile::SNamedChannel& R,
                  const SComprehensiveArtifactDetectionPPack& P);

void
detect_artifacts( sigfile::CSource& E,
                  const SComprehensiveArtifactDetectionPPack& P);

}}

#endif

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