/*
   HARK Library
   Copyright (C) 2021 Honda Research Institute Japan Inc.
 */

#if !defined(_HARKLIB_NODE_HARKFILEIO_H_INCLUDED_)
#define _HARKLIB_NODE_HARKFILEIO_H_INCLUDED_ 1

#include <iostream>
#include <fstream>
#include <vector>

////#ifdef ENABLE_HARKIO3
extern "C++"{
    #include "libharkio3.h"
}
////#endif	

#include "hark-lib/hark-lib.h"
#include "hark-lib/error.h"

#include "hark-lib/matrix.h"
#include "hark-lib/tf.h"

//#include "MICARY_struct.h"
//#include "MICARY_GHDSS_struct.h"

/*
struct MICARY_TFDBFileHeader {
    int lFs; // sampling frequency [Hz]
    int lNFFT; // FFT length [point]
    int lNMic; // num. of microphones
    int lNSrc; // num. of sound sources
    int lNFreq; // num. of frequency lines [line]
    int lMeshFlg; // 音源位置が格子状になっているかのflag
    int lMeshX; // X方向の格子数
    int lMeshY; // Y方向の格子数
    int lMeshZ; // Z方向の格子数
    int iVersion; // version
    int iFileType; // file type（0: TF_CONJ, 1: separation matrix）
    char cPad[92]; // padding
};
*/


namespace hark
{

class HarkFileIO 
{
public:
    enum class OPEN_MODE: int64_t {
        READ  = 0,
        WRITE = 1
    };

    enum class FORMAT_TYPE: int64_t {
        INVALID   = -1, // File is closed Pointer is invalid. (this->tfp == NULL)
        UNDEFINED = 0,  // This file was opened in write mode and the type is undefined.
        USER      = 1,  // This file stores user-defined matrices. Not checked by this class.
        TF        = 2,  // This file contains the Transfer Function.
        W         = 3   // This file contains the Separation Matrix.
    };

    constexpr static const char *HARKFILEIO_SIGNATURE_TFMAT = "transfer function";
    constexpr static const char *HARKFILEIO_SIGNATURE_SPMAT = "separation matrix";
    constexpr static const char *HARKFILEIO_COMPLEX_TYPESTR = "complex";

    std::vector<hark::Position> mics;
    std::vector<hark::Position> srcs;
    std::vector<hark::Position> mics_polar;
    std::vector<hark::Position> srcs_polar;
    std::vector<int> freqs;
    std::vector<std::complex<float> > locdata;
    std::vector<std::complex<float> > sepdata;
    int sampling_rate;
    int num_fft;

    size_t GetNumMic(){ return this->mics.size(); }
    size_t GetNumSrc(){ return this->srcs.size(); }
    size_t GetNumFreq(){ return this->freqs.size(); }
    size_t GetNumFFT(){ return static_cast<size_t>(this->num_fft); }
    size_t GetNumLocData(){ return this->locdata.size(); }
    size_t GetNumSepData(){ return this->sepdata.size(); }
    bool LocDataExists(){ return (!this->locdata.empty()); }
    bool SepDataExists(){ return (!this->sepdata.empty()); }

public:
    HarkFileIO();
    ~HarkFileIO();

    void OpenFile(const std::string &filename, OPEN_MODE mode = OPEN_MODE::READ);
    void ReopenFile(const std::string &filename, OPEN_MODE mode = OPEN_MODE::READ);
    void CloseFile();

    //ファイル読み込み
    //bool ReadHeader(const std::string &filename/*, TFDBFileHeader &TFDBHead*/);

    //データの読込み
    //bool ReadData(const std::string &filename/*,
    //              std::vector<Location> &srcs,
    //              std::vector<Location> &mics,
    //              std::vector<int> &freqs,
    //              std::vector<std::complex<float> > &data*/);

    // テキストファイル(xml)
    //bool LoadPositionData(const std::string &filename, std::vector<Location> &poses);

    // テキストファイル
    //bool LoadPositionData(const std::string &filename, std::vector<Location> &poses);

    // Neighborsリスト計算
    bool CalcNeighbors(const std::string &filename, float thresh);

    // 現在のTFからidを指定してposindexを取得
    int GetPosIndex(int id);

    // 現在のTFから座標を指定して最近接位置のidを取得
    int GetNearestPosID(hark::Position &cur);

    void SetW(const std::string &filename,
              std::vector<int> &freqs,
              std::vector<hark::Position> &mics,
              std::vector<hark::Position> &srcs,
              std::vector<std::complex<float> > &w);

    // ファイル作成 // MICARY_LocationArray->std::vector<Location>
    bool WriteData(const std::string &filename/*,
                   std::vector<std::complex<float> > &data,
                   std::vector<int> &freqs,
                   std::vector<Location> &srcs,
                   std::vector<Location> &mics*/);

    // メンバー
    std::string filename; // Transfer Function or Separation Matrix filename
    ::harkio_TransferFunction *ptf; // Transfer Function or Separation Matrix file pointer
    FORMAT_TYPE file_type;
    OPEN_MODE mode;

    // クラス内取得Neighborと取得条件
    // 注) this->pPrinbrsを使用する間はTFファイルを閉じないこと。poses配列はTFと共有している
    harkio_Neighbors *pPrinbrs; // クラス内で再計算したNeighbors
    float thresh; // m_fThresh スレッショルド(ユークリッド距離[m])

private:
    float _EuclidDistance(hark::Position &a, hark::Position &b);
};

}

#endif /* #if !defined(_HARKLIB_NODE_HARKFILEIO_H_INCLUDED_) */

/* end of file */
