#pragma once
#include "Screen.h"
#define VID_THREADED_MODEL 0

#if (VID_THREADED_MODEL)
#include <thread>
#include <mutex>
#include <condition_variable>
#endif

class CVideoProc
{
		CScreen            *m_pScreen;          // модуль подсистемы вывода на экран
		double              fMemoryTicks;
		double              fMemory_Mod;

	public:
		struct ThrOSCVars_t
		{
			// переменные для эмуляции луча ЭЛТ
			uint16_t nVideoAddress;     // видео адрес, младшие 6 бит - счётчик строк внутри строки
			bool    bHgate;             // флаг отсчёта служебных видеоциклов в строке
			bool    bVgate;             // флаг отсчёта служебных строк
			int     nVGateCounter;      // дополнительный счётчик служебных строк
			int     nLineCounter;       // счётчик видео строк

			void init()
			{
				clear();
			}
			void clear()
			{
				nVideoAddress = 0; // видео адрес, младшие 6 бит - счётчик строк внутри строки
				bHgate = false;
				bVgate = true;
				nVGateCounter = 64;
				nLineCounter = 0; // счётчик видео строк
			}

			ThrOSCVars_t &operator = (const ThrOSCVars_t &src)
			{
				memcpy(this, &src, sizeof(ThrOSCVars_t));
				return *this;
			}
			ThrOSCVars_t &operator = (const ThrOSCVars_t *src)
			{
				memcpy(this, src, sizeof(ThrOSCVars_t));
				return *this;
			}
		};

#if (VID_THREADED_MODEL)
		void                StopThread();
		bool                StartThread();
		void                ExecuteThreadFunc();    // собственно функция
		std::thread         m_ExecuteThread;
		bool                m_bThreadTerminate;   // флаг завершения потока
		bool                m_bNotify;  // флаг от ложных пробуждений потока
		std::mutex          m_mutThr;   // мутекс потока. залочен пока поток живой
		std::mutex          m_mutex;    // мутекс для синхронизации
		std::condition_variable m_cv;   // условная переменная, чтоб будить поток, когда надо
#endif

	protected:
		ThrOSCVars_t        m_sOSCV;

		void                Make_One_Screen_Cycle();

	public:
		CVideoProc();
		virtual ~CVideoProc();
		void                init();
		void                clear();
		void                uninit();

		inline void         SetScreen(CScreen *scr)
		{
			m_pScreen = scr;   // задание объекта экранной подсистемы. Он создаётся в другом месте
		}
		inline CScreen *GetScreenPtr()
		{
			return m_pScreen;
		}

		inline void SetOSCVars(const ThrOSCVars_t *pOSCV)
		{
			m_sOSCV = pOSCV;
		}

		inline ThrOSCVars_t *GetOSCVars()
		{
			return &m_sOSCV;
		}
		inline void         SetMod(const double f)
		{
			fMemory_Mod = f;
		}
		inline void         SetTicks(const double f)
		{
			fMemoryTicks = f;
		}
		inline double       GetTicks()
		{
			return fMemoryTicks;
		}

		void                InitEmulator();

		void                clock();
};

