
// BKTapeReaderDlg.h : файл заголовка
//

#pragma once
#include "AudioFile.h"
#include "GFResizeDialogHelper.h"
#include "WaveParserFront.h"
#include "WaveParserAmp.h"

#include <condition_variable>
#include <mutex>
#include <thread>
#include <queue>
#include <vector>

struct BinFile
{
	uint16_t addr;
	uint16_t len;
	uint16_t crc;
	CString strName;
	int     nCount;
	BinFile()
		: addr(0)
		, len(0)
		, crc(0)
		, nCount(0)
	{}
};

constexpr auto TAPE_UI_UPDATE = 110;


template <typename T>
class container
{
		std::recursive_mutex _lock;
		std::queue<T> _elements;
	public:
		void push(T element)
		{
			std::lock_guard<std::recursive_mutex> locker(_lock);
			_elements.push(element);
		}

		T get()
		{
			std::lock_guard<std::recursive_mutex> locker(_lock);
			T e = _elements.front();
			_elements.pop();
			return e;
		}

		bool empty()
		{
			std::lock_guard<std::recursive_mutex> locker(_lock);
			return _elements.empty();
		}
};





// диалоговое окно CBKTapeReaderDlg
class CBKTapeReaderDlg : public CDialogEx
{
// Создание
	public:
		CBKTapeReaderDlg(CWnd *pParent = nullptr);  // стандартный конструктор

		enum CHANS : int
		{
			LEFT_SRC = 0,   // левый канал
			RIGHT_SRC,      // правый канал
			MIX_SRC,        // микс левый+правый

			LEFT_ST1,
			LEFT_ST2,
			RIGHT_ST1,
			RIGHT_ST2,
			MIX_ST1,
			MIX_ST2,
			CHANNNELS
		};

// Данные диалогового окна
#ifdef AFX_DESIGN_TIME
		enum { IDD = IDD_BKTAPEREADER_DIALOG };
#endif
		void                    winprintf(const TCHAR *format, ...);

	protected:
		enum class PROC_TYPE { CONVOL_SIMSINE, CONVOL_DERIVATIVE, CONVOL_SINE, CORRELATION };
		enum class CONV_MODE { CONVOLUTION, CORRELATION };

		bool                    OpenFile(CString &strName);
		bool                    SaveFile(CString &strName);
		std::string             ConvertUnicodetoStr(UINT type, const CString &ustr);
		bool                    PreWork(CString &strInFileName);
		bool                    Work(int nFileNum, bool bSingle, int nTune1, int nTune2);
		void                    ParseFront(CHANS chn, CString strID);
		void                    ParseAmp(CHANS chn, CString strID);
		void                    ParseFunc(CWaveParserProto *wp, CHANS chn, CString strID);

		void                    Convol(WaveData &m, WaveData &s, WaveData &d, CONV_MODE mode);
		void                    Amplifier(WaveData &s);
		void                    Attenuator(WaveData &s, int val);

		void                    MixChn(WaveData &l, WaveData &r, WaveData &d);
		void                    PrepareTemplate(int slen, PROC_TYPE pt);

		CString                 SetNewName(CString &strOldName);

		void                    SetProgressRange(int start, int end);
		void                    SetProgressPos(int pos);

		bool                    SaveBinFile(CString &strFileName, TAPE_FILE_INFO *pTfi, uint8_t *pBin);

		void                    CheckUnSavedFile(TAPE_FILE_INFO *pTfi);


		// Реализация
	protected:
		HICON                   m_hIcon;
		GFResizeDialogHelper    m_Resizer;
		CProgressCtrl           m_Progress;

		AudioFile<double>       m_audioSrc;
		AudioFile<double>       m_audioFile;
		WaveData                m_temp;
		CString                 m_strCurrentPath;
		CString                 m_strCurrentFileName;

		CString                 m_strStage;
		int                     m_nBeginProgress;
		int                     m_nEndProgress;
		int                     m_nCurrentProgress;
		int                     m_nFilesNum;

		CWaveParserAmp          m_ParserAmp;
		CWaveParserFront        m_ParserFront;

		container<CString>      m_queList;      // список файлов в очереди
		std::thread             m_thrQueue;     // поток, который будет обрабатывать очередь
		volatile bool           m_bKillQueue;   // флаг остановки потока
		std::condition_variable m_queueCheck;
		std::mutex              m_lockQueue;
		std::mutex              m_lockQueueWork;
		void                    StartQueueThread();
		void                    StopQueueThread();
		void                    QueueWork();

		std::mutex              m_lockWork;     // мутекс, означающий что поток работает
		bool                    m_bKillWork;    // флаг остановки потока

		std::vector<BinFile>    m_vecSavedBins;
		std::vector<BinFile>    m_vecUnSavedBins;

		// Созданные функции схемы сообщений
		virtual void DoDataExchange(CDataExchange *pDX) override;   // поддержка DDX/DDV
		virtual BOOL OnInitDialog() override;
		afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
		afx_msg void OnPaint();
		afx_msg HCURSOR OnQueryDragIcon();
		afx_msg void OnDropFiles(HDROP hDropInfo);
		afx_msg void OnSize(UINT nType, int cx, int cy);
		afx_msg void OnGetMinMaxInfo(MINMAXINFO *lpMMI);
		afx_msg void OnClose();
		afx_msg void OnDestroy();
		afx_msg void OnTimer(UINT_PTR nIDEvent);
		afx_msg void OnBnClickedButtonSettings();
		DECLARE_MESSAGE_MAP()
};


