// (C) Copyright 2007 by Autodesk, Inc. 
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted, 
// provided that the above copyright notice appears in all copies and 
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting 
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC. 
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to 
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
//
/////////////////////////////////////////////////////////////////////
#include "stdafx.h"

#include "acm.h"
#include "acmdef.h"
#include "cauxent.h"
#include "stdMgr.h"
#include "symstd.h"
#include "symbol.h"
#include "EdgeSym.h"
#include "leader.h"

#include "dbobjptr.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
setEdgeValues(AmdtEdge* pEdge)
{
  // allow user to select all valid values for selected edge type
  Acm::Variable wVar[] = { Acm::EdgeMax, Acm::EdgeMin, Acm::EdgeSign};
  CString prompts[] = {"Max Value: ", "Min Value: ", "Sign Value: "};

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

  int ret = 0;
  // set max/min value to the symbol
  for(int i = 0; i < size - 1; i ++)
  {
    CString value;
    ret = acedGetString(1, prompts[i], value.GetBuffer(133));
    value.ReleaseBuffer();

    if(ret == RTCAN) return Adesk::kFalse;

    // set value to the symbol
    pEdge->setValue(wVar[i], (LPCTSTR)value);
  }

  CString sign;
  ret = acedGetString(1, prompts[2], sign.GetBuffer(133));
  sign.ReleaseBuffer();
  if (ret == RTCAN) return Adesk::kFalse;

  // set sign value to the symbol
  pEdge->setValue(Acm::EdgeSign, (LPCTSTR)sign);

  AmdtEdgeStd *pEdgeStd;
  if (Acad::eOk != (acdbOpenObject(pEdgeStd, pEdge->serverId(), AcDb::kForRead)))
    return Adesk::kFalse;

  // set properties for edge symbol
  pEdge->setMajority(Adesk::kFalse);
  pEdge->setAllAround(Adesk::kTrue);
  pEdge->setNewSymbolRev(Adesk::kTrue);
  pEdge->setStdNum(Adesk::kTrue);
  
  return Adesk::kTrue;
}

void createEdgeSym()
{
  // create edge symbol object
  AmdtEdge *pEdge = new AmdtEdge(); 
  assert(pEdge);
  if (Acm::eOk != pEdge->setSymbolDefaults()) {
    acutPrintf(_T("\nFail to set default for edge symbol."));
    delete pEdge;
    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 pEdge;
      return;
    }
    ptArr.append(pt);
  }
  pEdge->addLeader(ptArr);

  // set edge symbol properties.
  if (Adesk::kFalse == setEdgeValues(pEdge)) {
    delete pEdge;
    return;
  }

  // Post to Database
  AcDbObjectId objId;
  if (Acad::eOk != postToDb(pEdge, objId)) {
    delete pEdge;
    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 = pEdge->attachGeomRef(pKey, AcGePoint3d::kOrigin);
    if (Acm::eOk != es)
      acutPrintf(_T("\nFail to attach to geometry"));

    pKey->release();
  }

  pEdge->close();
}

//set edge standard properties.
void editEdgeStandard()
{
  // get current standard from standard manager.
  AcDbObjectId curStdId;
  acmStdMgr->getCurrent(curStdId);

  const AcDbObjectPointer<AcmStandard> pStd(curStdId, AcDb::kForRead);
  if (Acad::eOk != pStd.openStatus())
    return;

  // get edge symbol standard from standard manager.
  AcDbObjectId edgeStdId;
  if (Acad::eOk != pStd->getCurrentSymbolStd(ACRX_T("AmdtEdgeStd"), edgeStdId)) {
    acutPrintf(ACRX_T("The edge symbol is not supported by %s standard!"), pStd->name());
    return;
  }

  // open edge standard object for writing.
  AcDbObjectPointer<AmdtEdgeStd> pEdgeStd(edgeStdId, AcDb::kForWrite);
  if (Acad::eOk != pEdgeStd.openStatus()) {
    acutPrintf(ACRX_T("Edge standard can not be opened!\n"));
    return;
  }

  // edit edge standard properties.
 
  // toggle between fulllist and simplified
  if (pEdgeStd->fullList() == Adesk::kTrue)
    pEdgeStd->setFullList(Adesk::kFalse);
  else
    pEdgeStd->setFullList(Adesk::kTrue);

  // set display of standard revision
  pEdgeStd->setStdNumAllowed(Adesk::kTrue);

  // set arrow type
  pEdgeStd->setArrowType(Acm::kArrowClosed15);

  // set text height
  double txtHeight = pEdgeStd->textHeight();
  acutPrintf(_T("\nEnter new text height <%.2f>: "), txtHeight);
  int result = ads_getreal(NULL, &txtHeight);
  if (result == RTCAN || result == RTERROR)
    return;
  pEdgeStd->setTextHeight(txtHeight);

  // edit arrow scale
  double arrowScale = pEdgeStd->arwScale();
  acutPrintf(_T("\nEnter new arrow size <%.2f>: "), arrowScale);
  result = ads_getreal(NULL, &arrowScale);
  if (result == RTCAN || result == RTERROR)
    return;
  pEdgeStd->setArwScale(arrowScale);

  // get leader color.
  int leaderColor = pEdgeStd->leaderTrueColor().colorIndex();
  acutPrintf(_T("\nEnter new leader color <%d>: "), leaderColor);
  result = ads_getint(NULL, &leaderColor);
  if (result == RTCAN || result == RTERROR)
    return;

  // set leader color.
  AcCmColor color;
  color.setColorIndex(leaderColor);
  pEdgeStd->setLeaderTrueColor(color);
  
  // get text color
  int textColor = pEdgeStd->textTrueColor().colorIndex();
  acutPrintf(_T("\nEnter new text color <%d>: "), textColor);
  result = ads_getint(NULL, &textColor);
  if (result == RTCAN || result == RTERROR)
    return;

  // set text color
  color.setColorIndex(textColor);
  pEdgeStd->setTextTrueColor(color);

  acutPrintf(_T("set edge standard properties successful."));
}