// GPGGAData.cpp: implementation of the CGPGGAData class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "taxi4u.h"
#include "GPRMCData.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
const double _PI = 3.14159265359;
const double _2PI = 3.14159265359*2;

float CGPRMCData::c_Lat = 0.0f;
float CGPRMCData::c_Lon = 0.0f;
CString CGPRMCData::c_GprmcData = L"";

CGPRMCData::CGPRMCData()
{
}

CGPRMCData::~CGPRMCData()
{
}

BOOL CGPRMCData::ParseData(const CString& szGPSData)
{
  CStringArray datas;  
  if(szGPSData.GetLength()>0)
  {
    int pos=-1;
    CString tmp = szGPSData;
    while(tmp.GetLength()>0)
    {  
      CString data;
      pos=tmp.FindOneOf(L",");
      if(pos>-1)
      {
        data=tmp.Mid(0,pos);
        tmp=tmp.Mid(pos+1);
      }
      else
      {
        data=tmp;
        tmp="";
      }
      datas.Add(data);
      //MYTRACE(L"GPS Data: %s",data);
    }
  }
  if(datas.GetSize()<12)
    return FALSE;

  if(datas.GetAt(2)!=_T("A"))
    return FALSE;

  //Check GPS Data Type
  if(datas.GetAt(0)!=_T("$GPRMC"))
  {
    return FALSE;
  }
  
  //Get UTC Time hhmmss.sss
  CString szUTCTime=datas.GetAt(1);
  if(szUTCTime.GetLength()==10)
  {
    m_UTCDataTime.wHour=(WORD)_ttoi(szUTCTime.Mid(0,2));
    m_UTCDataTime.wMinute=(WORD)_ttoi(szUTCTime.Mid(2,2));
    m_UTCDataTime.wSecond=(WORD)_ttoi(szUTCTime.Mid(4,2));
    m_UTCDataTime.wMilliseconds=(WORD)_ttoi(szUTCTime.Mid(7,3));    
  }
  else
    return FALSE;
  //MYTRACE(L"GPS UTC Time: %s",szUTCTime);
  
  //Get UTC Date ddmmyy
  CString szUTCDate=datas.GetAt(9);
  if(szUTCDate.GetLength()==6)
  {    
    m_UTCDataTime.wDay=(WORD)_ttoi(szUTCDate.Mid(0,2));
    m_UTCDataTime.wMonth=(WORD)_ttoi(szUTCDate.Mid(2,2));
    m_UTCDataTime.wYear=2000+(WORD)_ttoi(szUTCDate.Mid(4,2));
  }
  else
    return FALSE;
  //MYTRACE(L"GPS UTC Date: %s",szUTCDate);
  
  //Get X Direction E,W
  CString szXDir=datas.GetAt(6);  
  if(szXDir.GetLength()!=1)
  {    
    return FALSE;
  }
  
  //Get X dddmm.mmmm
  CString szX=datas.GetAt(5);
  if(szX.GetLength()==10)
  {
    int ddd=_ttoi(szX.Mid(0,3));
    int mm=_ttoi(szX.Mid(3,2));
    int mmmm=_ttoi(szX.Mid(6,4));
    double x=ddd+(mm+mmmm/10000.0)/60.0;  
    //double x=ddd*100+mm+mmmm/10000.0f;
    if(szXDir=="W" || szXDir=="w")
    {
      x=-x;
    }
    m_Lon=(float)x;
  }
  else
    return FALSE;

  //MYTRACE(L"GPS X: %s",szX);
  
  
  //Get Y Direction N,S
  CString szYDir=datas.GetAt(4);
  if(szYDir.GetLength()!=1)
  {    
    return FALSE;
  }

  //Get Y ddmm.mmmm
  CString szY=datas.GetAt(3);
  if(szY.GetLength()==9)
  {
    int dd=_ttoi(szY.Mid(0,2));
    int mm=_ttoi(szY.Mid(2,2));
    int mmmm=_ttoi(szY.Mid(5,4));
    
    double y=dd+(mm+mmmm/10000.0)/60.0;
    //double y=dd*100+mm+mmmm/10000.0f;
    if(szYDir=="S" || szYDir=="s")
    {
      y=-y;
    }
    m_Lat=(float)y;
  }
  else
    return FALSE;
  //MYTRACE(L"GPS Y: %s",szY);

  //assign to global lat/lon
  c_GprmcData = szGPSData;
  c_Lat = m_Lat;
  c_Lon = m_Lon;

  return TRUE;
}

BOOL CGPRMCData::CheckSum(const CString& szGPSData)
{
  TRY
  {
        int pos = -1;
    if((pos = szGPSData.FindOneOf(L"*")) == -1)
      return FALSE;
    
        CString szChkSum = szGPSData.Mid(pos+1, szGPSData.GetLength());
        CString szChkStr = szGPSData.Left(pos);
    
        short nSum = 0;
        int nLen = szChkStr.GetLength();
    
        for (int i = 1; i < nLen; i++)
        {
            short ch = szChkStr.GetAt(i);
            nSum = nSum ^ ch;
        }
        CString szXorSum = L"";
        szXorSum.Format(L"%0X", nSum);
    
        if(szXorSum.GetLength() == 1)
            szXorSum.Insert(0, '0');
    
        if(szChkSum.Compare(szXorSum) == 0)
            return TRUE;
  }
  CATCH(CException, e)
  {
  }
  END_CATCH
  return FALSE;
}

BOOL CGPRMCData::IsLocationTriggered(const float x_Lat, const float x_Lon, const float x_Rad)
{  
  TRY
  {
    double rLat1 = c_Lat * _PI / 180;
    double rLon1 = c_Lon * _PI / 180;
    double rLat2 = x_Lat * _PI / 180;
    double rLon2 = x_Lon * _PI / 180;
    
    double dDist = acos(cos(rLat1) * cos(rLon1) * cos(rLat2) * cos(rLon2) + cos(rLat1) * sin(rLon1) * cos(rLat2) * sin(rLon2) + sin(rLat1) * sin(rLat2)) * 6378.137 * 1000;    
    //MYTRACE(L"Dist %0.1f, mLatLon[%0.4f, %0.4f], xLatLon[%0.4f, %0.4f]", dDist, m_Lat, m_Lon, x_Lat, x_Lon);

    if (dDist <= x_Rad)
      return TRUE;
  }
  CATCH(CException, e)
  {
  }
  END_CATCH
  return FALSE;
}