#include "StdAfx.h"
#include "NetProtocol.h"

NetProtocol::NetProtocol(void)
{
  this->Clear();
}

NetProtocol::~NetProtocol(void)
{
  this->Clear();
}

void NetProtocol::Clear()
{
  this->nSize = 0;
  memset(this->bContent, 0, sizeof(this->bContent));
}

void NetProtocol::AddContent(byte b)
{
  this->AddContent(&b, 1);
}

void NetProtocol::AddContent(pbyte pBuf, int nSize)
{
  memcpy(&this->bContent[this->nSize], pBuf, nSize);
  this->nSize += nSize;
}

void NetProtocol::GetContent(pbyte* pPtr, long* nSize)
{
  if (nSize)
  {
    *pPtr = this->bContent;
    *nSize = this->nSize;
  }
}

/* ********************************************************************************************************* */

DeviceProtocol::DeviceProtocol(void) {}

DeviceProtocol::~DeviceProtocol(void) {}

PFTC DeviceProtocol::GetDeviceContent()
{
  return this->bContent;
}

long DeviceProtocol::GetDeviceContentSize()
{
  return this->nSize;
}

void DeviceProtocol::AddSeparator()
{
  this->AddContent('|');
}

void DeviceProtocol::AddTerminator()
{
  this->AddContent('#');
}

int DeviceProtocol::GetFlexStrHexToLong(const int beg, const int len)
{
  char buf[PDA_BODY_PACKET_SIZE];
  memset(buf, 0, sizeof(buf));
  memcpy(buf, &this->bContent[beg], len);
  return strtol(buf, NULL, 16);
}

int DeviceProtocol::GetDeviceId()
{
  char buf[PDA_BODY_PACKET_SIZE];
  memset(buf, 0, sizeof(buf));
  memcpy(buf, &this->bContent[3], 6);
  return atoi(buf);
}

int DeviceProtocol::GetType()
{
  return this->GetFlexStrHexToLong(10, 2);
}

int DeviceProtocol::GetCode()
{
  return this->GetFlexStrHexToLong(13, 2);
}

int DeviceProtocol::GetReferenceId()
{
  return this->GetFlexStrHexToLong(16, 4);
}

int DeviceProtocol::GetLength()
{
  return this->GetFlexStrHexToLong(21, 2);
}

PFTC DeviceProtocol::GetPayload()
{
  return &this->bContent[Device_PACKET_HEAD_SIZE];
}

int DeviceProtocol::GetCheckSum()
{
  return this->GetFlexStrHexToLong(Device_PACKET_HEAD_SIZE+this->GetLength()+1, 2);
}

bool DeviceProtocol::VerifyCheckSum()
{
  short sXor = 0;
  char b[2] = {0};
  int nCheckSize = this->nSize-3;

  if (this->nSize >= (Device_PACKET_HEAD_SIZE+Device_PACKET_TAIL_SIZE))
  {
    for (int i = 0; i < nCheckSize; i++)  
      sXor ^= this->bContent[i];

    sprintf(b, "%02X", sXor);
    if (strncmp(b, (const char*) &this->bContent[nCheckSize], 2) == 0)
      return true;
  }
  return false;
}

bool DeviceProtocol::VerifyHeader(const pbyte pContent, const int nSize)
{
  byte b[Device_PACKET_SIZE] = {0};
  memcpy(b, pContent, nSize);

  if (nSize > 2)
  {
    if (strncmp((const char*) b, ">H|", 3) == 0)
      return true;
  }
  return false;
}

bool DeviceProtocol::VerifyTerminator()
{
  if (this->nSize > 0)
  {
    if (this->bContent[this->nSize-1] == '#')
      return true;
  }
  return false;
}

bool DeviceProtocol::VerifyDeviceProtocolString()
{
  if (this->nSize >= (Device_PACKET_HEAD_SIZE+Device_PACKET_TAIL_SIZE))
  {
    if (this->VerifyHeader(this->bContent, this->nSize) && this->VerifyTerminator() && this->VerifyCheckSum())
      return true;
  }
  return false;
}

void DeviceProtocol::AddCheckSum()
{
  short sXor = 0;
  char cs[2] = {0};
  byte bs[2] = {0};

  for (int i = 0; i < this->nSize; i++)  
    sXor ^= this->bContent[i];

  sprintf(cs, "%02X", sXor);
  memcpy(bs, cs, 2);
  this->AddContent(bs, 2);
}

/*
void DeviceProtocol::AddDeviceProtocolString(const pbyte pContent, const int nSize)
{
  if (this->VerifyHeader(pContent, nSize))
  {
    this->SetDeviceProtocolString(pContent, nSize);
  }
  else
  {
    if (this->nSize > Device_PACKET_SIZE / 2)
      this->Clear();

    memcpy(&this->bContent[this->nSize], pContent, nSize);
    this->nSize+=nSize;
  }
}
*/

void DeviceProtocol::AddDeviceProtocolString(const pbyte pContent, const int nSize)
{
  static byte bContent[Device_PACKET_SIZE] = {0};
  int  bSize = 0;

  memset(bContent, 0, sizeof(bContent));

  if (this->GetRealDeviceProtocolString(pContent, nSize, bContent, bSize))
  {
    if (this->VerifyHeader(bContent, bSize))
    {
      this->SetDeviceProtocolString(bContent, bSize);
    }
    else
    {
      if (this->nSize > Device_PACKET_SIZE / 2)
        this->Clear();

      memcpy(&this->bContent[this->nSize], bContent, bSize);
      this->nSize+=bSize;
    }
  }
}

int DeviceProtocol::GetCharacterPosition(const pbyte pContent, const int nSize, const char ch, const bool bRev /* = false */)
{
  if (!bRev)
  {
    for (int ipos = 0; ipos < nSize; ipos++)
    {
      if (pContent[ipos] == ch)
        return ipos;
    }
  }
  else
  {
    for (int ipos = nSize-1; ipos > 0; ipos--)
    {
      if (pContent[ipos] == ch)
        return ipos;
    }
  }
  return 0;
}

bool DeviceProtocol::GetRealDeviceProtocolString(const pbyte pContent, const int nSize, byte* ppContent, int& nnSize)
{
  if (ppContent)
  {
    memset(ppContent, 0, Device_PACKET_SIZE);
    memcpy(ppContent, pContent, nSize);
    nnSize = nSize;
    int ipos = 0;

    if (ipos = GetCharacterPosition((const pbyte) ppContent, nnSize, '>'))
    {
      nnSize = nSize-ipos;
      memset(ppContent, 0, Device_PACKET_SIZE);
      memcpy(ppContent, pContent+ipos, nnSize);
    }

    if ((ipos = GetCharacterPosition((const pbyte) ppContent, nnSize, '#', true)) > 0)
    {
      nnSize = ipos+1;
      ppContent[nnSize+0]=0;
      ppContent[nnSize+1]=0;
    }
    return true;
  }
  return false;
}

void DeviceProtocol::SetDeviceProtocolString(const pbyte pContent, const int nSize)
{
  this->Clear();
  memcpy(this->bContent, pContent, nSize);
  this->nSize = nSize;
}

void DeviceProtocol::SetDeviceProtocolString(const int nDevId, const int pType, const int pCode, const int pRefId, const int pLen, const pbyte pBuf)
{
  this->Clear();
  char cuf[Device_PACKET_HEAD_SIZE] = {0};
  byte buf[Device_PACKET_HEAD_SIZE] = {0};

  sprintf(cuf, ">H|%06d|%02X|%02X|%04X|%02X|", nDevId, pType, pCode, pRefId, pLen);
  memcpy(buf, cuf, Device_PACKET_HEAD_SIZE);

  this->AddContent(buf, Device_PACKET_HEAD_SIZE);
  this->AddContent(pBuf, pLen);
  this->AddSeparator();
  this->AddCheckSum();
  this->AddTerminator();
}

/* ********************************************************************************************************* */
#ifdef _WIN32
#ifndef _CONSOLE

PdaProtocol::PdaProtocol(void) {}

PdaProtocol::~PdaProtocol(void) {}

PPLC PdaProtocol::GetPdaProtocolString()
{
  return this->bPayload;
}

int PdaProtocol::GetPdaContentType()
{
  return this->nPayloadType;
}

long PdaProtocol::GetPdaContentSize()
{
  return this->nPayloadSize;
}

long PdaProtocol::GetPdaContentLength()
{
  return this->nPayloadLength;
}

bool PdaProtocol::VerifyContent(pbyte pPayload)
{
  if (pPayload)
  {
    int nContentSize = _tcslen((PTCHAR) pPayload);
    if (nContentSize >= PDA_HEADER_SIZE)
    {
      CString str;
      str.Format(L"%s", pPayload);
      str.Format(L"%c", str.GetAt(PDA_HEADER_SIZE-1));

      if (str.Compare(_T(PDA_CONTENT_SEPARATOR)) == 0)
        return true;
    }
  }
  return false;
}

void PdaProtocol::SetPdaProtocolString(pbyte pPayload)
{
  if (pPayload && this->VerifyContent(pPayload))
  {
    TCHAR tch[PDA_BODY_PACKET_SIZE] = {0};
    memcpy(tch, pPayload, 4);

    this->nPayloadType = _wtoi(tch);
    this->nPayloadLength = _tcslen((PTCHAR) pPayload);
    this->nPayloadSize = this->nPayloadLength * sizeof(TCHAR);
    memset(this->bPayload, 0, sizeof(this->bPayload));
    memcpy(this->bPayload, pPayload, this->nPayloadSize);
  }
}

void PdaProtocol::SetPdaProtocolString(const int pType, char* sContent[])
{
  TCHAR tch[PDA_BODY_PACKET_SIZE] = {0};
  char sbuf[PDA_BODY_PACKET_SIZE] = {0};

  sprintf(sbuf, "%02d%s", pType, PDA_CONTENT_SEPARATOR);

  for (int i = 0; sContent[i] != NULL; i++)
  {
    strcat(sbuf, sContent[i]);
    strcat(sbuf, PDA_CONTENT_DELIMENTOR);
  }
  this->nPayloadType = pType;
  MultiByteToWideChar(CP_ACP, 0, sbuf, -1, tch, sizeof(tch));
  this->nPayloadLength = _tcslen(tch);
  this->nPayloadSize = this->nPayloadLength * sizeof(TCHAR);
  memset(this->bPayload, 0, sizeof(this->bPayload));
  memcpy(this->bPayload, tch, this->nPayloadSize);
}

void PdaProtocol::SetPdaProtocolString(const int ptype, CStringArray* sContent)
{
  CString str=L"";
  str.Format(L"%02d%s", ptype, PDA_CONTENT_SEPARATOR);

  for (int i = 0; i < sContent->GetCount(); i++)
  {
    str.Append(sContent->GetAt(i));
    str.Append(TEXT(PDA_CONTENT_DELIMENTOR));
  }
  this->nPayloadType = ptype;
  this->nPayloadLength = str.GetLength();
  this->nPayloadSize = this->nPayloadLength * sizeof(TCHAR);
  memset(this->bPayload, 0, sizeof(this->bPayload));
  memcpy(this->bPayload, str.GetString(), this->nPayloadSize);
}

void PdaProtocol::Tokenize(const CString& str, CStringArray* sContent, const CString& delimiters /* = L */)
{
  CString tmp=L"";

  int lpos = 0;
  int cpos = str.FindOneOf(delimiters);

  if (cpos != -1 && sContent)
  {
    while (true)
    {
      tmp = str.Mid(lpos, cpos-lpos);

      if (tmp.GetLength() == 0)
        break;

      sContent->Add(tmp);
      lpos = cpos+1;
      cpos = str.Find(delimiters, lpos);

      if (cpos == -1)
        cpos = str.GetLength();
    }
  }
}

void PdaProtocol::GetPdaContent(CStringArray *sContent)
{
  CString str;
  CStringArray payload, content;
  str.SetString((PTCHAR) this->bPayload, this->nPayloadLength);

  if (sContent)
  {
    this->Tokenize(str, &payload, TEXT(PDA_CONTENT_SEPARATOR));
    this->Tokenize(payload.GetAt(1), &content, TEXT(PDA_CONTENT_DELIMENTOR));

    for (int i = 0; i < content.GetSize(); i++)
      sContent->Add(content.GetAt(i));
  }
}

#endif
#endif