#include "StdAfx.h"
#include "PdaAPI.h"

PdaAPI::PdaAPI(void)
{  
}

PdaAPI::~PdaAPI(void)
{
}

void PdaAPI::api_Set_Incomming_Callback(void (*CallBackFunctionName)(const CallBackSruct, CStringArray *, void *), void *context)
{
  if (CallBackFunctionName)
  {
    CallBackFunc_Inc_Payload=CallBackFunctionName;
    inc_payload_func_context=context;
  }
}

bool PdaAPI::SendAcknowledgement(const PFlexTracPacket pftp)
{
  if (pftp->pcode == FT_CODE_REQ)
  {
    if (this->api_IsConnected())
    {  
      pbyte pPacket;

      long psize = 0;
      this->m_ftSend.SetFlexTracProtocolString(pftp->pdeviceid, pftp->ptype, FT_CODE_ACK, pftp->prefid, 0, NULL);
      this->m_ftSend.GetContent(&pPacket, &psize);

      if (this->m_hSerial.WriteData(pPacket, psize) <= 0)
        return false;
    }
  }
  return true;
}

void PdaAPI::ProcessIncommingData(const PFlexTracPacket pftp)
{
  if (this->CallBackFunc_Inc_Payload)
  {  
    static CStringArray sa;
    CallBackSruct cbData;
    sa.RemoveAll();

    cbData.nType = PDA_TYPE_DEBUG;
    cbData.nCode = pftp->pcode;
    cbData.nReferenceId = pftp->prefid;

    if (pftp->plength == 0)
    {
      this->CallBackFunc_Inc_Payload(cbData, &sa, this->inc_payload_func_context);
    }
    else if (this->m_pdaRecv.VerifyContent(pftp->ppayload))
    {
      this->m_pdaRecv.SetPdaProtocolString(pftp->ppayload);
      this->m_pdaRecv.GetPdaContent(&sa);  
      cbData.nType = this->m_pdaRecv.GetPdaContentType();
      this->CallBackFunc_Inc_Payload(cbData, &sa, this->inc_payload_func_context);
    }
  }  
}

void PdaAPI::ProcessInTrackerData(const PFlexTracPacket pftp)
{
  if (this->CallBackFunc_Inc_Payload)
  {  
    static CStringArray sa;
    CallBackSruct cbData;
    sa.RemoveAll();

    cbData.nType = PDA_TYPE_DEBUG;
    cbData.nCode = pftp->pcode;
    cbData.nReferenceId = pftp->prefid;

    if (pftp->plength != 0)
    {
      char* arr[2] = {0};
      arr[0] = (char*) pftp->ppayload;
      arr[1] = NULL;

      this->m_pdaRecv.SetPdaProtocolString(PDA_TYPE_TRACKER_DATA, arr);
      this->m_pdaRecv.GetPdaContent(&sa);  
      cbData.nType = this->m_pdaRecv.GetPdaContentType();
      this->CallBackFunc_Inc_Payload(cbData, &sa, this->inc_payload_func_context);
    }
  }
}

void PdaAPI::OnDataFromPort(void* data, DWORD nDataCount, void* context)
{  
  struct FlexTracPacket ftPacket = {0};
  PPdaAPI pParent = (PPdaAPI) context;

  if (pParent && nDataCount > 0)
  {
    pParent->m_ftRecv.AddFlexTracProtocolString((pbyte) data, nDataCount);

    if (pParent->m_ftRecv.VerifyFlextracProtocolString())
    {
      memset(&ftPacket, 0, sizeof(ftPacket));
      ftPacket.pdeviceid = pParent->m_ftRecv.GetDeviceId();
      ftPacket.ptype = pParent->m_ftRecv.GetType();
      ftPacket.pcode = pParent->m_ftRecv.GetCode();
      ftPacket.prefid   = pParent->m_ftRecv.GetReferenceId();
      ftPacket.plength = pParent->m_ftRecv.GetLength();
      memcpy(ftPacket.ppayload, pParent->m_ftRecv.GetPayload(), ftPacket.plength);

      switch (ftPacket.ptype)
      {
        case FT_TYPE_UC1_POLL:
          pParent->SendNextDataInQueue(ftPacket.pdeviceid);
          break;

        case FT_TYPE_UC6_PDATA:
        case FT_TYPE_UC7_PDATA:
        case FT_TYPE_UC9_CALLCENTER:
          pParent->SendAcknowledgement(&ftPacket);
          pParent->ProcessIncommingData(&ftPacket);
          break;

        case FT_TYPE_UC8_TDATA:
          pParent->SendAcknowledgement(&ftPacket);
          pParent->ProcessInTrackerData(&ftPacket);
          break;

        default:
          break;
      }
    }
  }
}

bool PdaAPI::api_Connect(const int nPort)
{
  this->m_hSerial.Set_Data_Callback(OnDataFromPort, this);

  if (this->m_hSerial.OpenPort(nPort, CBR_9600))
    return true;

  return false;
}

bool PdaAPI::api_IsConnected()
{
  return this->m_hSerial.IsOpen();
}

bool PdaAPI::api_Disconnect()
{
  return this->m_hSerial.ClosePort();
}

bool PdaAPI::dbg_SendPoll()
{
  pbyte pPacket;

  if (this->api_IsConnected())
  {    
    long psize = 0;
    this->m_ftSend.SetFlexTracProtocolString(PDA_FT_TEST_DEVICE_ID, FT_TYPE_UC1_POLL, FT_CODE_REQ, 0, psize, NULL);
    this->m_ftSend.GetContent(&pPacket, &psize);

    if (this->m_hSerial.WriteData(pPacket, psize) > 0)
      return true;
  }
  return false;
}

bool PdaAPI::dbg_SendTrackerData(const char* stdata)
{
  pbyte pPacket;

  if (this->api_IsConnected())
  {    
    long psize = 0;
    this->m_ftSend.SetFlexTracProtocolString(PDA_FT_TEST_DEVICE_ID, FT_TYPE_UC8_TDATA, FT_CODE_REQ, 0, strlen(stdata), (const pbyte) stdata);
    this->m_ftSend.GetContent(&pPacket, &psize);

    if (this->m_hSerial.WriteData(pPacket, psize) > 0)
      return true;
  }
  return false;
}

bool PdaAPI::dbg_SendData(const PTCHAR payload, const int nDevId /* = 0 */)
{
  pbyte pPacket;

  if (this->api_IsConnected())
  {   
    int ptype = 0;
    long psize = lstrlen(payload) * sizeof(TCHAR);
    ptype = ((nDevId == 0) ? FT_TYPE_UC6_PDATA : FT_TYPE_UC7_PDATA);

    this->m_pdaSend.SetPdaProtocolString((pbyte) payload);

    if (this->m_pdaSend.GetPdaContentType() == PDA_TYPE_CALL_CENTER)
      ptype = FT_TYPE_UC9_CALLCENTER;

    this->m_ftSend.SetFlexTracProtocolString(nDevId, ptype, FT_CODE_REQ, 0, psize, (pbyte) payload);
    this->m_ftSend.GetContent(&pPacket, &psize);

    if (this->m_hSerial.WriteData(pPacket, psize) > 0)
      return true;
  }
  return false;
}

bool PdaAPI::SendNextDataInQueue(const int nDevId)
{
  bool bRet = false;

  if (this->m_qSendArr.GetCount() > 0)
  {
    CString str = this->m_qSendArr.GetAt(0);
    bRet = this->dbg_SendData(str.GetBuffer(), nDevId);
    this->m_qSendArr.RemoveAt(0);
  }
  return bRet;
}

bool PdaAPI::QueueSendData(const PTCHAR payload)
{  
  this->m_qSendArr.Add(payload);
  return true;
}

void PdaAPI::dbg_GetQueuedData(CStringArray* &szArr)
{
  szArr = &this->m_qSendArr;
}

bool PdaAPI::pda_Login(const CString& driverid)
{
  CString str=L"";
  str.Format(L"%d%s%s%s", PDA_TYPE_LOGIN, PDA_CONTENT_SEPARATOR, driverid, PDA_CONTENT_DELIMENTOR);
  return this->QueueSendData(str.GetBuffer());
}

bool PdaAPI::pda_Logout(const CString& driverid)
{
  CString str=L"";
  str.Format(L"%d%s%s%s", PDA_TYPE_LOGOUT, PDA_CONTENT_SEPARATOR, driverid, PDA_CONTENT_DELIMENTOR);
  return this->QueueSendData(str.GetBuffer());
}

bool PdaAPI::pda_LoginSuccess(const CString& drivername)
{
  CString str=L"";
  str.Format(L"%d%s%s%s", PDA_TYPE_LOGIN_SUCC, PDA_CONTENT_SEPARATOR, drivername, PDA_CONTENT_DELIMENTOR);
  return this->dbg_SendData(str.GetBuffer());
}

bool PdaAPI::pda_LoginFail()
{
  CString str=L"";
  str.Format(L"%d%s%s%s", PDA_TYPE_LOGIN_FAIL, PDA_CONTENT_SEPARATOR, L"", PDA_CONTENT_DELIMENTOR);
  return this->dbg_SendData(str.GetBuffer());
}

bool PdaAPI::pda_LoginFailCall()
{
  CString str=L"";
  str.Format(L"%d%s%s%s", PDA_TYPE_LOGIN_FAIL_CALL, PDA_CONTENT_SEPARATOR, L"", PDA_CONTENT_DELIMENTOR);
  return this->dbg_SendData(str.GetBuffer());
}

bool PdaAPI::pda_CallCenter()
{
  CString str=L"";
  str.Format(L"%d%s%s%s", PDA_TYPE_CALL_CENTER, PDA_CONTENT_SEPARATOR, L"", PDA_CONTENT_DELIMENTOR);
  return this->QueueSendData(str.GetBuffer());
}

bool PdaAPI::pda_HasPassengerWaiting(const CString& driverid, const CString& msg)
{
  //CTimeSpan cts = CTime::GetCurrentTime() - CTime(0);
  //cts.GetTotalSeconds()

  CString str=L"";
  str.Format(L"%d%s%s%s%s", PDA_TYPE_HAS_PASS_WAITING, PDA_CONTENT_SEPARATOR, driverid, PDA_CONTENT_DELIMENTOR, msg);
  return this->QueueSendData(str.GetBuffer());
}

bool PdaAPI::pda_OrderAccept(const CString& driverid, const CString& orderid)
{
  CString str=L"";
  str.Format(L"%d%s%s%s%s", PDA_TYPE_ORDER_ACCEPT, PDA_CONTENT_SEPARATOR, driverid, PDA_CONTENT_DELIMENTOR, orderid);
  return this->QueueSendData(str.GetBuffer());
}

bool PdaAPI::pda_OrderDispatch(const CString& driverid, const CString& orderid)
{
  CString str=L"";
  str.Format(L"%d%s%s%s%s", PDA_TYPE_ORDER_DISPATCH, PDA_CONTENT_SEPARATOR, driverid, PDA_CONTENT_DELIMENTOR, orderid);
  return this->QueueSendData(str.GetBuffer());
}

bool PdaAPI::pda_OrderComplete(const CString& driverid, const CString& orderid)
{
  CString str=L"";
  str.Format(L"%d%s%s%s%s", PDA_TYPE_ORDER_COMPLETE, PDA_CONTENT_SEPARATOR, driverid, PDA_CONTENT_DELIMENTOR, orderid);
  return this->QueueSendData(str.GetBuffer());
}

bool PdaAPI::pda_TrafficNews(const CString& msg)
{
  CString str=L"";
  str.Format(L"%d%s%s%s", PDA_TYPE_TRAFFIC_NEWS, PDA_CONTENT_SEPARATOR, msg, PDA_CONTENT_DELIMENTOR);
  return this->dbg_SendData(str.GetBuffer());
}

bool PdaAPI::pda_PassengerWaitLocation(const CString& msg)
{
  CString str=L"";
  str.Format(L"%d%s%s%s", PDA_TYPE_HPW_LOCATION, PDA_CONTENT_SEPARATOR, msg, PDA_CONTENT_DELIMENTOR);
  return this->dbg_SendData(str.GetBuffer());
}

bool PdaAPI::pda_MiscellaneousInfo(const CString& msg)
{
  CString str=L"";
  str.Format(L"%d%s%s%s", PDA_TYPE_MISC_INFO, PDA_CONTENT_SEPARATOR, msg, PDA_CONTENT_DELIMENTOR);
  return this->dbg_SendData(str.GetBuffer());
}

bool PdaAPI::pda_OrderRequest(const CString& orderid, const CString& ordermsg)
{
  CString str=L"";
  str.Format(L"%d%s%s%s%s", PDA_TYPE_ORDER_REQUEST, PDA_CONTENT_SEPARATOR, orderid, PDA_CONTENT_DELIMENTOR, ordermsg);
  return this->dbg_SendData(str.GetBuffer());
}

bool PdaAPI::pda_OrderRequest(const CString& orderid, const CString& name, const CString& loc, const CString& dest, const CString& time)
{
  CString str=L"";
  str.Format(L"%d%s%s%s%s%s%s%s%s%s%s", PDA_TYPE_ORDER_REQUEST, PDA_CONTENT_SEPARATOR, orderid, PDA_CONTENT_DELIMENTOR, name, PDA_CONTENT_DELIMENTOR, loc, PDA_CONTENT_DELIMENTOR, dest, PDA_CONTENT_DELIMENTOR, time);
  return this->dbg_SendData(str.GetBuffer());
}

bool PdaAPI::pda_OrderConfirm(const CString& driverid, const CString& orderid)
{
  CString str=L"";
  str.Format(L"%d%s%s%s%s", PDA_TYPE_ORDER_CONFIRM, PDA_CONTENT_SEPARATOR, driverid, PDA_CONTENT_DELIMENTOR, orderid);
  return this->dbg_SendData(str.GetBuffer());
}

bool PdaAPI::pda_OrderCancel(const CString& driverid, const CString& orderid)
{
  CString str=L"";
  str.Format(L"%d%s%s%s%s", PDA_TYPE_ORDER_CANCEL, PDA_CONTENT_SEPARATOR, driverid, PDA_CONTENT_DELIMENTOR, orderid);
  return this->dbg_SendData(str.GetBuffer());
}

bool PdaAPI::pda_ReservationDispatch(const CString& driverid, const CString& orderid)
{
  CString str=L"";
  str.Format(L"%d%s%s%s%s", PDA_TYPE_RESV_DISPATCH, PDA_CONTENT_SEPARATOR, driverid, PDA_CONTENT_DELIMENTOR, orderid);
  return this->QueueSendData(str.GetBuffer());
}

bool PdaAPI::pda_ReservationComplete(const CString& driverid, const CString& orderid)
{
  CString str=L"";
  str.Format(L"%d%s%s%s%s", PDA_TYPE_RESV_COMPLETE, PDA_CONTENT_SEPARATOR, driverid, PDA_CONTENT_DELIMENTOR, orderid);
  return this->QueueSendData(str.GetBuffer());
}

bool PdaAPI::pda_ReservationReceipt(const CString& driverid, const CString& orderid)
{
  CString str=L"";
  str.Format(L"%d%s%s%s%s", PDA_TYPE_RESV_RECEIPT, PDA_CONTENT_SEPARATOR, driverid, PDA_CONTENT_DELIMENTOR, orderid);
  return this->QueueSendData(str.GetBuffer());
}

bool PdaAPI::pda_ReservationCancel(const CString& driverid, const CString& orderid)
{
  CString str=L"";
  str.Format(L"%d%s%s%s%s", PDA_TYPE_RESV_CANCEL, PDA_CONTENT_SEPARATOR, driverid, PDA_CONTENT_DELIMENTOR, orderid);
  return this->dbg_SendData(str.GetBuffer());
}