//////////////////////////////////////////////////////////////////////////////
//
//  Copyright 2025 Autodesk, Inc.  All rights reserved.
//
//  Use of this software is subject to the terms of the Autodesk license 
//  agreement provided at the time of installation or download, or which 
//  otherwise accompanies this software in either electronic or hard copy form.   
//
//////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "acm.h"
#include "acmdef.h"
#include "cauxent.h"
#include "stdmgr.h"
#include "bommgr.h"
#include "symstd.h"
#include "leader.h"
#include "symbol.h"
#include "bomstd.h"
#include "partref.h"

Acad::ErrorStatus postToDb(AcDbEntity* ent, AcDbObjectId& objId);
static Adesk::Boolean editStringMap(const CMapStringToString& valueMap);

Adesk::Boolean 
editStringMap(CMapStringToString& valueMap)              
{
  POSITION pos = valueMap.GetStartPosition();
  CString value, tmp, key, prompt;
  while( pos != NULL ) {
    // Gets key (string) and value (pPerson)
    valueMap.GetNextAssoc( pos, key,value );
    prompt.Format(_T("\nSet value for %s <%s> :"),key,value);
    if( ads_getstring(1,prompt,tmp.GetBuffer(150), 150) == RTCAN) return Adesk::kFalse;
    tmp.ReleaseBuffer();
    if( tmp == _T(".") ) value = _T("");
    if( tmp != _T("") ) value = tmp;
    valueMap.SetAt(key,value);
  }
  return Adesk::kTrue;
}


void partref()
{
  // gets a point in drawing
  AcGePoint3d pnt;
  int res = ads_getpoint(NULL,_T("\nSelect point :"),asDblArray(pnt));
  if( res == RTCAN || res == RTERROR ) return;

  // creates new instance of AcmPartRef and sets defaults
  AcmPartRef *pRef = new AcmPartRef;
  pRef->setSymbolDefaults(); // will create data id, because we didn't initialize it.
  pRef->setOrigin(pnt);

  // attempts to add partref to database
  AcDbObjectId partId;
  if ( postToDb(pRef, partId) != Acad::eOk) {
    delete pRef;
    return;
  }
  pRef->close();

  // gets current BOM standard
  CMapStringToString valueMap;
  AcDbObjectId stdId;
  if (acmStdMgr->getCurrent(stdId) != Acm::eOk)
    return;
    
  AcmStandard* pStandard;
  if (acdbOpenObject(pStandard, stdId, AcDb::kForRead))
    return;
  
  // get BOM Standard
  AcDbObjectId bomStdId;
  if(pStandard->getCurrentSymbolStd(_T("AcmBOMStd"), bomStdId) != Acad::eOk){
    pStandard->close();
    return;
  }
  pStandard->close();

  AcmBOMStd* pBomStd; 
  if (acdbOpenObject(pBomStd, bomStdId, AcDb::kForRead))
    return;

  // prepares valueMap to get user's data for partref
  CString numItemColumnName=_T("");
  Adesk::Int16 numOfItems = 1;
  Adesk::Int16 len = pBomStd->columnLength();
  for (int i=0; i<len; i++){
    const AcmCColumnDef* pColumn = ((const AcmBOMStd*)pBomStd)->column(i);
    switch (pColumn->type()){
    case Acm::kItem :
      // Item number is saved in BOM row 
      break;
    case Acm::kQuantity :
      // number of Items  
      numItemColumnName = pColumn->name();
      valueMap.SetAt(pColumn->name(), _T("1"));
      break;
    default :
      valueMap.SetAt(pColumn->name(), _T(""));
      break;
    }
  }
  pBomStd->close();

  // gets partref's data and assigns them to the newly created partref
  if(editStringMap(valueMap)){
    CString val;
    if (valueMap.Lookup(numItemColumnName, val)){
      numOfItems = _ttoi(val);
    }
    acmBomMgr->setPartData(partId,numOfItems,valueMap);
  }
}


