//////////////////////////////////////////////////////////////////////////////
//
//  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 "symstd.h"

Adesk::Boolean containString(const CStringArray& array,
                             const CString& item)
{
  for (int j=0;j<array.GetSize();j++) {
    if (item.Compare((LPCTSTR)array[j]) == 0) return Adesk::kTrue;
  }
  return Adesk::kFalse;
}

/////////////////////////////////////////////////////////////////
// adds standard (not used yet) to drawing
/////////////////////////////////////////////////////////////////
void createStd()
{
  //get all registered classes derived and include AcmStandard
  //
  AcDbVoidPtrArray rxClassArray;
  if (Acm::eOk != acmStdMgr->getRegisteredStd(_T("AcmStandard"),rxClassArray))
    return;

  //get all standards loaded in the drawing
  //
  AcmStandard *pStd;
  CStringArray stdNameArray;
  AcDbObjectIdArray idStdArray;
  if (Acm::eOk != acmStdMgr->getStandards(idStdArray))
  {
      //    return;
  }

  for (int i=0;i<idStdArray.length();i++) {
    if (Acad::eOk != acdbOpenObject(pStd,idStdArray[i],AcDb::kForRead))
      continue;

    stdNameArray.Add(pStd->name());
    pStd->close();
  }
  
  //print-out all standard names (not used yet)
  //
  CString stdName;
  AcDbIntArray stdOfferedArray;
  acutPrintf(_T("\nRegistered standards:"));
  for (int i=0;i<rxClassArray.length();i++) {
    pStd = (AcmStandard*)((AcRxClass*)rxClassArray[i])->create();
    if (!pStd) continue;
    stdName = pStd->originalName();
    delete pStd;

    //standard is already in the drawing
    if (containString(stdNameArray,stdName)) continue;

    stdOfferedArray.append(i);
    acutPrintf(_T("\n %2d : %s"),stdOfferedArray.length(),(LPCTSTR)stdName);
  }

  if (stdOfferedArray.length() < 1) {
    acutPrintf(_T("\nNo standard to create!"));
    return;
  }

  //default standard is ANSI
  CString prompt;
  acmStdMgr->getDefaultStd(stdName);

  if (!containString(stdNameArray,stdName)) {
    prompt.Format(_T("\nSelect standard to create <%s>:"),(LPCTSTR)stdName);
    ads_initget(RSG_NOZERO|RSG_NONEG,NULL);
  } else {
    prompt = _T("\nSelect standard to create :");
    ads_initget(RSG_NONULL|RSG_NOZERO|RSG_NONEG,NULL);
  }

  //user select standard to create
  int ret = 0;
  int rc = ads_getint((LPCTSTR)prompt,&ret);
  if ((rc != RTNORM) && (rc != RTNONE)) return;

  //add standard to the drawing
  AcDbObjectId idStd;
  if (rc == RTNONE) {
    CString stdName;
    acmStdMgr->getDefaultStd(stdName);
    acmStdMgr->addStandard(idStd,NULL,stdName);
    acutPrintf(_T("\nStandard was successfully created"));
  } else {
    if (ret > stdOfferedArray.length()) {
      acutPrintf(_T("\nInvalid number!"));
      return;
    }
    pStd = (AcmStandard*)((AcRxClass*)rxClassArray[stdOfferedArray[ret-1]])->create();
    assert(pStd != NULL);
    if (Acm::eOk != acmStdMgr->addStandard(idStd,pStd)) {
      delete pStd;
    } else {
      //here you can modify standard because acmStdMgr->addStandard calls
      //setFactoryDefaults() on passed standard (and all owned revision)
      //...
      pStd->close();
      acutPrintf(_T("\nStandard was succesfully created"));
    }
  }
}

/////////////////////////////////////////////////////////////////////
// unloads standard from drawing
/////////////////////////////////////////////////////////////////////
void removeStd()
{
  //get all standards loaded in the drawing
  //
  AcmStandard *pStd;
  AcDbObjectIdArray idStdArray;
  if (Acm::eOk != acmStdMgr->getStandards(idStdArray))
  {
      //    return;
  }
  for (int i=0;i<idStdArray.length();i++) {
    if (Acad::eOk != acdbOpenObject(pStd,idStdArray[i],AcDb::kForRead))
      continue;

    acutPrintf(_T("\n %2d : %s"),i+1,pStd->name());
    pStd->close();
  }
  if (idStdArray.length() < 1) {
    acutPrintf(_T("\nNo standard in the drawing!"));
    return;
  }

  int ret = 0;
  ads_initget(RSG_NONULL|RSG_NOZERO|RSG_NONEG,NULL);
  int rc = ads_getint(_T("\nRemove standard :"),&ret);
  if (rc != RTNORM) return;
  if (ret > idStdArray.length()) return;

  if (Acm::eStandardIsReferenced == acmStdMgr->removeStandard(idStdArray[ret-1])) {
    acutPrintf(_T("\nStandard is referenced"));
    return;
  }
  acutPrintf(_T("\nStandard was purged successfully"));
}

//////////////////////////////////////////////////////////////////////
// renames standard (that is already loaded in drawing)
//////////////////////////////////////////////////////////////////////
void renameStd()
{
  //get all standards loaded in the drawing
  //
  AcmStandard *pStd;
  AcDbObjectIdArray idStdArray;
  if (Acm::eOk != acmStdMgr->getStandards(idStdArray))
  {
      //    return;
  }
  for (int i=0;i<idStdArray.length();i++) {
    if (Acad::eOk != acdbOpenObject(pStd,idStdArray[i],AcDb::kForRead))
      continue;

    acutPrintf(_T("\n %2d : %s"),i+1,pStd->name());
    pStd->close();
  }
  if (idStdArray.length() < 1) {
    acutPrintf(_T("\nNo standard in the drawing!"));
    return;
  }

  int ret = 0;
  ads_initget(RSG_NONULL|RSG_NOZERO|RSG_NONEG,NULL);
  int rc = ads_getint(_T("\nStandard to rename:"),&ret);
  if (rc != RTNORM) return;
  if (ret > idStdArray.length()) return;

  CString retStr;
  ads_initget(RSG_NONULL,NULL);
  rc = ads_getstring(0,_T("\nNew standard name:"),retStr.GetBuffer(133), 133);
  retStr.ReleaseBuffer();
  if (RTNORM != ads_snvalid((LPCTSTR)retStr,FALSE)) {
    acutPrintf(_T("\nInvalid standard name"));
    return;
  }

  retStr.MakeUpper();
  if (Acm::eOk != acmStdMgr->renameStd(idStdArray[ret-1],(LPCTSTR)retStr)) {
    acutPrintf(_T("\nInvalid standard name"));
    return;
  }
  acutPrintf(_T("\nStandard was renamed successfully"));
}
