/////////////////////////////////////////////////////////////////////////////////////////
//
// Please refer to "COPYRIGHT.md" for the relevant copyright statement of this software.
//
/////////////////////////////////////////////////////////////////////////////////////////
//

#pragma once
#include "GcDbCore2dDefs.h"
#include "gcadstrc.h"
#include "GcString.h"

GCBASE_PORT Gcad::ErrorStatus gcutNewString(const GCHAR* pInput, GCHAR*& pOutput);

template<class ObjType>
inline Gcad::ErrorStatus gcutGetGcStringConvertToGChar(const ObjType* pObj,
                                                       Gcad::ErrorStatus (ObjType::*pFunc)(GcString&) const,
                                                       GCHAR*& pOutput)
{
  GcString sOutput;
  const Gcad::ErrorStatus es = (pObj->*pFunc)(sOutput);
  if (es != Gcad::eOk)
  {
    pOutput = nullptr;
    return es;
  }
  return ::gcutNewString(sOutput.kwszPtr(), pOutput);
}

template<class ObjType>
inline GCHAR* gcutGetGcStringConvertToGChar(const ObjType* pObj, Gcad::ErrorStatus (ObjType::*pFunc)(GcString&) const)
{
  GcString sOutput;
  const Gcad::ErrorStatus es = (pObj->*pFunc)(sOutput);
  GCHAR* pRet = nullptr;
  if (es == Gcad::eOk)
    ::gcutNewString(sOutput.kwszPtr(), pRet);
  return pRet;
}

inline GCHAR* gcutGcStringToGChar(const GcString& s, Gcad::ErrorStatus es)
{
  GCHAR* pBuf = nullptr;
  if (es == Gcad::eOk)
    ::gcutNewString(s.kwszPtr(), pBuf);
  return pBuf;
}
inline Gcad::ErrorStatus gcutGcStringToGChar(const GcString& s, GCHAR*& pBuf, Gcad::ErrorStatus es)
{
  pBuf = nullptr;
  if (es != Gcad::eOk)
    return es;
  return ::gcutNewString(s.kwszPtr(), pBuf);
}

inline int gcutCopyGdsResultStr(int nGdsResult, const wchar_t* pIn, wchar_t* pDestBuf, size_t nSizeDest)
{
  // Duplicate some return codes from adscodes.h
  const int gcedGDS_RTNORM = 5100;
  const int gcedGDS_RTERROR = -5001;
  const int gcedGDS_RTINPUTTRUNCATED = -5008;
  if (pDestBuf == nullptr || nSizeDest == 0)
    return gcedGDS_RTERROR; // invalid input
  *pDestBuf = L'\0'; // init dest buf to empty

  if (nGdsResult != gcedGDS_RTNORM)
    return nGdsResult; // on errors, return an empty buffer

  if (pIn == nullptr) // invalid input
    return gcedGDS_RTERROR;

  // Copy string until done or run out of buffer
  for (;; pIn++, pDestBuf++)
  {
    *pDestBuf = *pIn;
    if (*pDestBuf == L'\0')
      break; // normal end of copy
    nSizeDest--;
    if (nSizeDest == 0)
    { // ran out of dest room
      nGdsResult = gcedGDS_RTINPUTTRUNCATED;
      *pDestBuf = L'\0'; // overwrite last char to null terminate
      break;
    }
  }
  return nGdsResult;
}
