#ifndef OpenTestSystem_OtxDiagManager_DiagRuntimeSystem_VwMcd90DiagRuntimeSystem_H
#define OpenTestSystem_OtxDiagManager_DiagRuntimeSystem_VwMcd90DiagRuntimeSystem_H

#include "DiagRuntimeSystemDefs.h"
#include "IDiagRuntimeSystem.h"
#include <memory>
#include <string>
#include <map>
#include <functional>
#include <queue>
#include <future>
namespace OpenTestSystem { namespace OtxDiagManager { namespace DiagRuntimeSystem { namespace VwMcdWrapper {
	class DSystemEx;
	class EventHandler;
}}}}

namespace OpenTestSystem
{
	namespace OtxDiagManager
	{
		namespace DiagRuntimeSystem
		{
			/// <summary>
			/// Contains methods for accessing the VW-MCD from version 9.0
			/// </summary>
			class VwMcd90DiagRuntimeSystem :
				public OpenTestSystem::OtxDiagManager::Common::IDiagRuntimeSystem
			{
			public:
				/// <summary>
				/// Creates an instance of the VW-MCD with the given project and vehicle name
				/// </summary>
				DIAGRUNTIMESYSTEM_EXPORTS VwMcd90DiagRuntimeSystem();
				/// <summary>
				/// Creates an instance of the VW-MCD with the given project and vehicle name
				/// </summary>
				/// <param name="projectName">Name of the ODX runtime project</param>
				/// <param name="vehicleInfo">Shortname of the vehicle</param>
				DIAGRUNTIMESYSTEM_EXPORTS VwMcd90DiagRuntimeSystem(std::string projectName, std::string vehicleInfo);
				DIAGRUNTIMESYSTEM_EXPORTS virtual ~VwMcd90DiagRuntimeSystem();
				DIAGRUNTIMESYSTEM_EXPORTS Common::Result * Execute(const Common::Command & command) override;
				DIAGRUNTIMESYSTEM_EXPORTS Common::Result * ExecuteAsync(const Common::Command & command) override;
				DIAGRUNTIMESYSTEM_EXPORTS void SetAsyncResultHandler(std::function<void(const Common::Result&)> handler) override;
				DIAGRUNTIMESYSTEM_EXPORTS void SetExceptionHandler(std::function<void(const Common::Exception&)> handler) override;
			private:
				std::function<void(const Common::Result&)> _asyncResultHandler;
				std::function<void(const Common::Exception&)> _exceptionHandler;
				std::shared_ptr<VwMcdWrapper::DSystemEx> _dSystem;
				VwMcdWrapper::EventHandler* _eventHandler = nullptr;

				bool isRunning;
				std::mutex _mutex;
				std::mutex _CloseComChannelMutex;
				std::condition_variable _conditionVariable;
				std::thread _thread;
				std::promise<int> _promise;
				std::future<int> _future;
				std::queue<std::string> _completedCommandQueue;
				std::map<std::string, std::future<void>> _runningCommandMap;
				int _eventId;
				void RegisterEvents();
				void UnregisterEvents();
				void DoManageThreads();
				void DoExecuteAsync(const Common::Command & command);
				bool WaitQueueAvailable(int timeout);
				void WaitIfBusy();
			};
		}
	}
}
#endif // OpenTestSystem_OtxDiagManager_DiagRuntimeSystem_VwMcd90DiagRuntimeSystem_H