text: ﻿#include "StdAfx.h"
  #include "BaseQuery.h"
  
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  MWR::C3::Core::BaseQuery::BaseQuery(std::weak_ptr<DeviceBridge> sender)
  	: m_ReceivedOrWillBeSent(true)
  	, m_SenderChannel(sender)
  	, m_SequenceNumber(0)	/// THIS IS WRONG
  {
  	// TODO, parse query.
  }
  
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  MWR::C3::Core::BaseQuery::BaseQuery(ResponseType responseType)
  	: m_ReceivedOrWillBeSent(false)
  	, m_ResponseType(responseType)
  	, m_SequenceNumber(GenerateSequenceNumber())
  {
  
  }
  
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  void MWR::C3::Core::BaseQuery::SetResponseType(ResponseType responseType)
  {
  	m_ResponseType = responseType;
  }
  
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  MWR::ByteVector MWR::C3::Core::BaseQuery::CompileQueryHeader() const
  {
  	if (m_ResponseType == ResponseType::None)
  		return ByteVector{}.Write(GetProcedureNumber());
  
  	return ByteVector{}.Write(~GetProcedureNumber(), BuildSequenceNumberField(static_cast<std::uint8_t>(m_ResponseType)));
  }
  
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  std::uint8_t MWR::C3::Core::BaseQuery::BuildSequenceNumberField(std::uint8_t statusBits) const
  {
  	return (m_SequenceNumber & (3 << s_SequenceNumberBitLength)) & (statusBits << s_SequenceNumberBitLength);
  }
  
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  MWR::C3::Core::BaseQuery::SequenceNumberFieldUnderlyingType MWR::C3::Core::BaseQuery::GenerateSequenceNumber()
  {
  	static std::mutex accessMutex;
  	std::scoped_lock lock(accessMutex);
  
  	static SequenceNumberFieldUnderlyingType nextGlobalSequenceNumber = 0;
  	if (nextGlobalSequenceNumber & (3 << s_SequenceNumberBitLength))
  		return nextGlobalSequenceNumber = 0;
  
  	return nextGlobalSequenceNumber++;
  }
  
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  std::weak_ptr<MWR::C3::Core::DeviceBridge> MWR::C3::Core::BaseQuery::GetSenderChannel()
  {
  	return m_SenderChannel;
  }
  