// Change History
// 11/19/03 AV Development: Merging ...
// 11/19/03 AV Development: Merge Production version 7
// 10/29/03 AV Production: merge from development version 7
// 10/29/03 AV Production: 64 bit conversion

#include <stdlib.h>

#include "drs/drs_type.h"
#include "drs/drs_appl.h"
#include "drs/drs_fld.h"
#include "base/AT_StringFunctions.h"

// **************************************************************************
// DRS_Field
// **************************************************************************
DRS_Field::DRS_Field( DRS_Database const &rDB, byte *fp, byte *sSection, uint iID) : iFieldID(iID), rDatabase(rDB),
    bHide(false), ApportionLevel(0)
{
  DRS_FileKey key;
  byte buf[sizeof(DRS_Descriptor)+7] = "";

    wsprintfA( (LPSTR) key, "FieldDescr%u", iID);
    GetPrivateProfileStringA( (LPCSTR) sSection, (LPCSTR) key, "", (LPSTR) buf, sizeof(DRS_Descriptor) + 7, (LPCSTR) fp);
    Descr.Extract( buf);

    wsprintfA( (LPSTR) key, "FieldDefault%u", iID);
    GetPrivateProfileStringA( (LPCSTR) sSection, (LPCSTR) key, "", (LPSTR) buf, sizeof(DRS_Descriptor) + 7, (LPCSTR) fp);
    strDefault = (char*)buf;

    wsprintfA( (LPSTR) key, "FieldHide%u", iID);
    GetPrivateProfileStringA( (LPCSTR) sSection, (LPCSTR) key, "", (LPSTR) buf, sizeof(DRS_Descriptor) + 7, (LPCSTR) fp);
    bHide = UTL_String::GetBool(buf);

    wsprintfA( (LPSTR) key, "FieldReoccurGroup%u", iID);
    if(GetPrivateProfileStringA( (LPCSTR) sSection, (LPCSTR) key, "", (LPSTR) buf, sizeof(DRS_Descriptor) + 7, (LPCSTR) fp))
        strOccurGroup = (char *)buf;
    wsprintfA( (LPSTR) key, "FieldApportionLevel%u", iID);
    ApportionLevel = GetPrivateProfileIntA( (LPCSTR) sSection, (LPCSTR) key, 0, (LPSTR) fp);
}

uint DRS_Field::ApplID()
  const
{
  return rDatabase.DataFieldApplID(iFieldID);
}

uint DRS_Field::FieldOccurrences( DRS_RecordSet *pRecordSet)
  const
{
return pRecordSet->Record(rDatabase.ID())->getOccurCount(iFieldID);
}

// **************************************************************************
// DRS_FieldText
// **************************************************************************
DRS_FieldText::DRS_FieldText( DRS_Database const &rDB, byte *fp, byte *sSection, uint iID) : DRS_Field( rDB, fp, sSection, iID)
{
  DRS_FileKey key;

    wsprintfA( (LPSTR) key, "FieldWidth%u", iID);
    iWidth = GetPrivateProfileIntA( (LPCSTR) sSection, (LPCSTR) key, 0, (LPSTR) fp);
};

uint DRS_FieldText::MaxSize(bool CombineOccurs) const
{
  const fieldDesc *const fd = rDatabase.CoreDatabase()->getField(iFieldID);

  if(!fd->getMaxOccurs())
    return 0;

  uint sz = max(iWidth, fd->getMaxSize());
  return fd->combineOccurs() || CombineOccurs ? sz * fd->getMaxOccurs() + fd->getMaxOccurs() - 1 : sz;
}

uint DRS_FieldText::FieldWidth( DRS_RecordSet *pRecordSet) const
{
  const AT_Record * rec = pRecordSet->Record(rDatabase.ID());
  return( iWidth? min( iWidth * rec->getOccurCount( iFieldID),
                       rec->getFieldLength( iFieldID)) :
                       rec->getFieldLength( iFieldID));
}

uint DRS_FieldText::FieldLen( DRS_RecordSet *pRecordSet, uint iState, uint iOcc) const
{
  const AT_Record * rec = pRecordSet->Record(rDatabase.ID());
  return( iWidth? min( iWidth, std::strlen((const char*) rec->getField( iFieldID, iOcc, 0))) :
    std::strlen((const char*) rec->getField( iFieldID, iOcc, 0)));
}

const byte * DRS_FieldText::FieldData( DRS_RecordSet *pRecordSet, uint iState, uint iOcc, byte *sDest, uint iDestLen) const
{
  if( ! sDest) return NULL;

  *sDest = 0;

  AT_Num val;
  const byte *pData = pRecordSet->Record(rDatabase.ID())->getField( iFieldID, iOcc, &val);

  if (!pData || !*pData)
  {
    memcpy(sDest, strDefault.c_str(), min(iDestLen, strDefault.length() + 1));
    return sDest;
  }

  if( iWidth)
    {
    std::strncpy( (char*) sDest, (const char*) pData, min(iDestLen ? iDestLen : iWidth, iWidth));
    if( iWidth < iDestLen) sDest[iWidth] = 0;
    return sDest;
    }
  else if( iDestLen)
    {
    std::strncpy( (char*) sDest, (const char*) pData, iDestLen);
    return sDest;
    }
  else
    return pData;
}

// **************************************************************************
// DRS_Integer
// **************************************************************************
DRS_FieldInteger::DRS_FieldInteger( DRS_Database const &rDB, byte *fp, byte *sSection, uint iID) : DRS_Field( rDB, fp, sSection, iID)
{
  DRS_FileKey key;

    wsprintfA( (LPSTR) key, "FieldWidth%u", iID);
    iWidth = GetPrivateProfileIntA( (LPSTR) sSection, (LPCSTR) key, 0, (LPSTR) fp);
}

uint DRS_FieldInteger::MaxSize(bool CombineOccurs) const
{
  const fieldDesc *const fd = rDatabase.CoreDatabase()->getField(iFieldID);

  if(!fd->getMaxOccurs())
    return 0;

  byte buf[35];
  uint len = std::strlen(ultoa(fd->getMaxSize(), (char*) buf, 10));
  uint sz = max(iWidth, len);
  return fd->combineOccurs() || CombineOccurs ? sz * fd->getMaxOccurs() + fd->getMaxOccurs() - 1 : sz;
}

uint DRS_FieldInteger::FieldWidth( DRS_RecordSet *pRecordSet) const
{
  const AT_Record * rec = pRecordSet->Record( rDatabase.ID());
  return( max( iWidth * rec->getOccurCount( iFieldID),
               rec->getFieldLength( iFieldID)));
}

uint DRS_FieldInteger::FieldLen( DRS_RecordSet *pRecordSet, uint iState, uint iOcc) const
{
  return( max( iWidth, std::strlen( (const char*) pRecordSet->Record(rDatabase.ID())->getField( iFieldID, iOcc, 0))));
}

const byte * DRS_FieldInteger::FieldData( DRS_RecordSet *pRecordSet, uint iState, uint iOcc, byte *sDest, uint iDestLen) const
{
  if( ! sDest) return NULL;

  AT_Num val;
  const byte *pData = pRecordSet->Record(rDatabase.ID())->getField( iFieldID, iOcc, &val);
  AT_Assert( pData, pData, "Field Data");

  *sDest = 0;
  
  if (!pData || !*pData)
  {
    memcpy(sDest, strDefault.c_str(), min(iDestLen, strDefault.length() + 1));
    return sDest;
  }

  if( iWidth)
    {
    uint datalen = std::strlen( (const char*) pData);
    iDestLen = iDestLen ? iDestLen : iWidth;
    if( iWidth > datalen)
      {
      uint off = iWidth - datalen;
      memset( sDest, '0', min(off, iDestLen));
      if( iDestLen <= off) return NULL;
      //iDestLen -= (iWidth - datalen);
      std::strncpy( (char*) sDest + off, (const char*) pData, min(datalen, iDestLen - off));
      sDest[min((uint)iWidth, (uint)iDestLen-1)] = 0;
      }
    else
      {
      std::strncpy( (char*) sDest, (const char*) pData, min( datalen, iDestLen));
      sDest[min(datalen, iDestLen-1)] = 0;
      }
    }
  else if( iDestLen)
    std::strncpy( (char*) sDest, (const char*) pData, iDestLen);
  else
    return pData;

  sDest[iDestLen-1] = 0;
  return sDest;
}

// **************************************************************************
// DRS_FieldMapped
// **************************************************************************
/*
DRS_FieldMapped::DRS_FieldMapped( DRS_Database const &rDB, byte *fp, byte *sSection, uint iID,
                                  DRS_FieldMap const &rMap)
                                  : DRS_Field( rDB, fp, sSection, iID), pFieldMap( &rMap)
{
}

uint DRS_FieldMapped::MaxSize(bool CombineOccurs) const
{
  return pFieldMap->MaxEntryLength();
}

uint DRS_FieldMapped::FieldLen( DRS_RecordSet *pRecordSet, uint iState, uint iOcc) const
{
  AT_Num val = 0;
  pRecordSet->Record(rDatabase.ID())->getField( iFieldID, iOcc, &val);
  return std::strlen( (const char*) pFieldMap->Entry( (uint)val).State(iState));
}

uint DRS_FieldMapped::FieldWidth( DRS_RecordSet  *) const
{
  return pFieldMap->MaxEntryLength();
}

const byte *DRS_FieldMapped::FieldData( DRS_RecordSet *pRecordSet, uint iState, uint iOcc, byte *sDest, uint iDestLen) const
{
  if( !sDest) return NULL;

  AT_Num val = 0;

  pRecordSet->Record(rDatabase.ID())->getField( iFieldID, iOcc, &val);

  //Vals must be bumped up one for index into map since map contains
  //"Any plan".
  val += 1;

  if( !val) //Vals of -1 : no data
    {
    sDest[0] = 0;
    return sDest;
    }

  if( iDestLen)
    std::strncpy( (char*) sDest, (const char*) pFieldMap->Entry( (uint)val).State(iState), iDestLen);
  else
    return pFieldMap->Entry( (uint)val).State(iState);
    
  sDest[iDestLen-1] = 0;

  return sDest;
}
*/
