//////////////////////////////////////////////////////////////////////////////
//
//  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 "symstd.h"
#include "leader.h"
#include "symbol.h"
#include "Weldsym.h"

#include "mibase.h"
#include "migeom.h"
#include "miStatus.h"

Acad::ErrorStatus postToDb(AcDbEntity* ent, AcDbObjectId& objId);

//MCAD API
AmiStatus amiPick2 ( TCHAR* prompt, AmiKeyType type, struct resbuf* entmask,
                    AmiPickObj& pickObj, Adesk::Boolean allowGhost );
AmiStatus amiGetKeyFromPick ( AmiPickObj* pPickObj, AmiKeyType& type, 
                              AmiObjectKey*& pObjKey );


Adesk::Boolean
setWeldingValues(AcmWelding* pWelding)
{
  AcmWeldingStd *pWeldStd;
  if (Acad::eOk != acdbOpenObject(pWeldStd,pWelding->serverId(),AcDb::kForRead))
    return Adesk::kFalse;

  //set default subwelding as empty
  pWelding->setType(Acm::kNoneSymbol,Adesk::kTrue);
  pWelding->setType(Acm::kNoneSymbol,Adesk::kFalse);

  //set welding symbol as field all-around weld
  pWelding->setFieldWeld(Adesk::kTrue);
  pWelding->setAreaDescType(Acm::kWeldAllAround);

  //get all supported weld types from standard
  AcmCObjArray<AcmCSymbolDesc> weldList;
  pWeldStd->getWelds(pWelding->subWelding(0), Acm::kForArrowSide, weldList);

  //printout welds selection
  acutPrintf(_T("\nOffered welds for arrow side:"));
  acutPrintf(_T("\n  0 : None weld symbol"));
  AcmCWeldService *pServ;
  for (int i=0;i<weldList.length();i++) {
    pServ = pWeldStd->getService(weldList[i]->type());
    assert(pServ);
    acutPrintf(_T("\n%3d : %s"),i+1,pServ->serviceName());
  }
  
  //user have select weld type
  int ret = 0;
  int rc = ads_getint(_T("\n\nSelect weld type :"),&ret);
  if ((rc != RTNORM) || (ret < 0) || (ret > weldList.length())) {
    pWeldStd->close();
    return Adesk::kFalse;
  }
  //set selected weld type
  if (ret == 0) {
    pWelding->setType(Acm::kNoneSymbol);
    return Adesk::kTrue;
  } else {
    pWelding->setType(weldList.at(ret-1)->type());
  }
  
  //init texts, labels and other values in symbol for obtain dlgInfo
  //It also inits variables which are possible to set for selected weld types
  //each weld type should have only several valid values such are size,depth,pitch...
  //This also checks all associations between welds on arrow and other side
  //(it should be identification line, ...)
  //You can call AcmCWeldService::initFields separately for each valid AcmCWeld
  //in each subwelding. Following function call initialization for whole subwelding
  pWeldStd->initFields(pWelding->subWelding(0));
  pWeldStd->close();

  //allow user to select all valid values for selected weld type
  Acm::Variable wVar[] = { Acm::WeldSize, Acm::WeldThickness, Acm::WeldLength,
    Acm::WeldNumber, Acm::WeldSpacing, Acm::WeldAngle, Acm::WeldDepth, Acm::WeldPitch,
    Acm::WeldGap, Acm::WeldClearance, Acm::WeldBacking,Acm::WeldNotes };

  int size = sizeof(wVar) / sizeof(wVar[0]);
  acutPrintf(_T("\nSet values for:\n"));

  CString prompt;
  for (int i=0;i<size;i++) {
    //is value valid for selected type
    if (pWelding->variableStatus(wVar[i]) != Acm::kVisible) continue;

    //obtain information (label text only in our case)
    CVarDlgInfo dlgInfo;
    pWelding->getVarDlgInfo(wVar[i],dlgInfo);
    
    //user set new value
    CString resultStr;
    prompt.Format(_T("%s :"),dlgInfo.label());
    rc = ads_getstring(1,prompt,resultStr.GetBuffer(133),133);
    resultStr.ReleaseBuffer();
    if (rc == RTCAN) return Adesk::kFalse;
    
    //value set to the symbol
    pWelding->setValue(wVar[i],(LPCTSTR)resultStr);
  }

  return Adesk::kTrue;
}

// test example how to create welding - symbol with simple leader, no landing
void welding()
{
  // create new instance of AcmWelding and set symbol defaults
  AcmWelding *pWelding = new AcmWelding(); 
  assert(pWelding);
  if( pWelding->setSymbolDefaults() != Acm::eOk) {
    acutPrintf(_T("\nCannot setup welding symbol for current standard."));
    delete pWelding;
    return;
  }

  // get starting and ending point of leader
  int res;
  AcGePoint3dArray ptArr;
  for( int i = 0; i<2; i++ ) {
    AcGePoint3d pt;
    res = ads_getpoint(NULL, _T("\nSelect point :"),asDblArray(pt));
    if (res != RTNORM){
      delete pWelding;
      return;
    }
    ptArr.append(pt);
  }
  pWelding->addLeader(ptArr);

  //set orientation of welding symbol
  if (ptArr[0].x < ptArr[1].x)
    pWelding->setOrientation(Acm::kRightSide);
  else
    pWelding->setOrientation(Acm::kLeftSide);

  // set values for welding
  if (!setWeldingValues(pWelding)) {
     delete pWelding;
     return;
  }
  
  // Post to Database
  //
  AcDbObjectId objId;
  if (postToDb(pWelding, objId) != Acad::eOk) {
    delete pWelding;
    return;
  }

  AmiPickObj pickObj;
  AmiObjectKey* pKey = NULL;
  Ami::KeyType type;
  AmiStatus as = Ami::eOk;
  as = amiPick2( _T("Select geometry:"), Ami::curveKey, NULL, pickObj, Adesk::kFalse);
  if (as.success()) {
    as = amiGetKeyFromPick(&pickObj, type, pKey);
    if (as.failure()) {
      TSTDSTRING strErrText = as.text();
      acutPrintf(_T("\nFail to get selected geometry. %s"), strErrText.c_str());
    }
  }
  //You can attach symbol now. attachGeomRef accept only keys derived from
  //AmiGeomKey.
  if (pKey) {
    Acm::ErrorStatus es = pWelding->attachGeomRef(pKey, AcGePoint3d::kOrigin);
    if (Acm::eOk != es)
      acutPrintf(_T("\nFail to attach to geometry"));

    pKey->release();
  }

  pWelding->close();
}
