#pragma once

#include <vector>

#pragma pack(push)
#pragma pack(1) // envelope period (envT, R13-R14) has invalid word alignment
struct TAPE_FILE_INFO
{
	DWORD               start_tuning;
	DWORD               synchro_start;
	DWORD               marker1;
	DWORD               synchro_header;
	DWORD               header;
	uint16_t            address;
	uint16_t            length;
	uint8_t             name[16];
	DWORD               marker2;
	DWORD               synchro_data;
	DWORD               data;
	uint16_t            crc;
	DWORD               synchro6;
	DWORD               end_tuning;
	DWORD               end;
};
#pragma pack(pop)

//макросы
#ifndef SAFE_DELETE
#define SAFE_DELETE(p)       { if (p) { delete (p);     (p)=nullptr; } }
#endif
#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p);   (p)=nullptr; } }
#endif
#ifndef SAFE_DELETE_MEMORY
#define SAFE_DELETE_MEMORY(p) { if (p) { free(p);   (p)=nullptr; } }
#endif
#ifndef SAFE_DELETE_OBJECT
#define SAFE_DELETE_OBJECT(p)   { if (p) { DeleteObject(p); (p)=nullptr; } }
#endif
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p)      { if (p) { (p)->Release(); (p)=nullptr; } }
#endif
#ifndef SAFE_RELEASE_C
#define SAFE_RELEASE_C(p)      { if (p) { (p).Release(); } }
#endif

using WaveData = std::vector<double>;

// разброс параметров относительно идеала
// тут главное не переборщить с допуском
//constexpr double dDelta = 0.3;

class CBKTapeReaderDlg;
class CWaveParserProto
{
	protected:

		int                     m_nPos;
		double                  m_dPrevV;
		bool                    m_bInverse;
		uint8_t                *m_pBin;
		double                  m_dAvgLength;

		CBKTapeReaderDlg       *m_pParent;

		double                  m_nAverage;

		virtual int             CalcImpLength(WaveData &pWave, int &pos) = NULL;
		virtual bool            FindMarker1(WaveData &pWave) = NULL;

		virtual bool            FindTuning(bool bRollback, WaveData &pWave, int nLength, DWORD &wave_pos, int &wave_length);
		virtual bool            FindMarker(WaveData &pWave);
		virtual bool            FindSyncro6(WaveData &pWave);
		virtual bool            ReadBit(WaveData &pWave, bool &bBit);
		virtual bool            ReadByte(WaveData &pWave, uint8_t &byte);

		int                     DefineLength(int nLength);

		void                    CalcAverage(WaveData &pWave);

		double MinusDelta(double x);
		double PlusDelta(double x);

	public:
		enum { BAD_LENGTH = -1, BAD_TUNING = -2, BAD_MARKER = -3};
		CWaveParserProto()
			: m_nPos(0)
			, m_dPrevV(0.0)
			, m_dAvgLength(0.0)
			, m_bInverse(false)
			, m_pBin(nullptr)
			, m_pParent(nullptr)
			, m_nAverage(0)
		{ };
		virtual ~CWaveParserProto()
		{
			SAFE_DELETE_ARRAY(m_pBin);
		};

		void                    bindDialog(CBKTapeReaderDlg *pDlg)
		{
			m_pParent = pDlg;
		}

		bool                    ParseWaveFile(TAPE_FILE_INFO *pTfi, WaveData &pWave, CString &name, CString strID);

		uint8_t                *getBin()
		{
			return m_pBin;
		}
		uint16_t                CalcCRC(TAPE_FILE_INFO *pTfi);
		double                  GetAvgImpLen()
		{
			return m_dAvgLength;
		}

};

