//
//  (C) Copyright 2009 by Autodesk, Inc.  All rights reserved.
//
// 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 "folder.h"

//  the main function
//
void folder_main()
{
  AcDbObjectId *circleObjId = new AcDbObjectId();
	AmiFolderKey *pNewFolder1 = new AmiFolderKey();
	AmiFolderKey *pNewFolder2 = new AmiFolderKey();
	createFolders(circleObjId, pNewFolder1, pNewFolder2);
  modifyFolders(circleObjId, pNewFolder1);

  AmiFolderDefKey *pNewFolder3Def = new AmiFolderDefKey();
  AmiFolderKey *pNewFolder3 = new AmiFolderKey();
  nestFolders(pNewFolder1, pNewFolder2, pNewFolder3Def, pNewFolder3);

  Adesk::Boolean es;
  es=selectionMode(pNewFolder1, pNewFolder3Def, pNewFolder3);
  if (!es) acutPrintf(_ACRX_T("Operation canceled!"));

	//ZoomAll();
}


// --------------- create folders ---------------
Adesk::Boolean createFolders(
	AcDbObjectId *&circleObjId,
	AmiFolderKey *&pNewFolder1,
  AmiFolderKey *&pNewFolder2) {

  AcDbObjectId rectangleObjId;

  AcDbObjectIdArray entities;
  AmiFolderDefKey *pNewFolder1Def = nullptr;
  AcGePoint3d center = AcGePoint3d(30,30,0);
  double radius = 10;
  AcDbCircle *pCircle1 = new AcDbCircle();

  AcGePoint3dArray ptArr;
  ptArr.setLogicalLength(4);
  ptArr[0].set(10, 50, 0.0);
  ptArr[1].set(50, 50, 0.0);
  ptArr[2].set(50, 10, 0.0);
  ptArr[3].set(10, 10, 0.0);
  AcDb2dPolyline *pRectangle1 = new AcDb2dPolyline(AcDb::k2dSimplePoly, ptArr, 0.0, Adesk::kTrue);

  AcGeMatrix3d newFolder1GeMatrix;  
  AcGeVector3d newFolder1Translation;

  // Step 1
  // create circle 
  pCircle1->setCenter(center);
  pCircle1->setRadius(radius);
  postToDb(pCircle1, *circleObjId);
  entities.append(*circleObjId);

  // create rectangle
  pRectangle1->makeClosed();
  postToDb(pRectangle1, rectangleObjId);
  entities.append(rectangleObjId);
  
  // Step 2
  // set translations
  newFolder1Translation.set(10,10,00);
  newFolder1GeMatrix.setTranslation(newFolder1Translation);

  // create folder
  ami2DSCreateFolderDef(
    pNewFolder1Def,
    pNewFolder1,
    entities,
    NULL,
    newFolder1GeMatrix,
    NULL,
    _ACRX_T("Folder1"));

  // Step 3
  // set translations
  newFolder1Translation.set(60,10,00);
  newFolder1GeMatrix.setTranslation(newFolder1Translation);

  // add new instance
  if(pNewFolder1Def)
  {
      ami2DSInstanceFolder(
          pNewFolder1Def,
          NULL,
          newFolder1GeMatrix,
          pNewFolder2);
  }
  
  return Adesk::kTrue;
}


// --------------- modify folders ---------------
Adesk::Boolean modifyFolders(
  AcDbObjectId *&circleObjId,
  AmiFolderKey *&pNewFolder1) {

  AcDbObjectIdArray entities;
  AcDbObjectId diagonal1ObjId;
  AcDbObjectId diagonal2ObjId;

  AcDbLine *pDiagonal1 = new AcDbLine();
  AcDbLine *pDiagonal2 = new AcDbLine();

  AcDbDatabase *pWorkingDb = acdbHostApplicationServices()->workingDatabase();
  AmiFolderKey *pEditTarget = new AmiFolderKey();
  AmiFolderKey *pActiveTarget = NULL;

  // Step 1
  // remove the circle entity from newFolder
  entities.append(*circleObjId);
  amiRemoveViewEntities(entities);

  // Step 2a
  // add first diagonal line to newFolder using amiAddEntitiesToFolder
  pDiagonal1->setStartPoint(AcGePoint3d(10,50,0));
  pDiagonal1->setEndPoint(AcGePoint3d(50,10,0));
  postToDb(pDiagonal1, diagonal1ObjId);
  entities.insertAt(0,diagonal1ObjId);

  amiAddEntitiesToFolder(entities,pNewFolder1);

  // Step 2b
  // add second diagonal line to newFolder using gMgr.EditTarget
  pDiagonal2->setStartPoint(AcGePoint3d(50,50,0));
  pDiagonal2->setEndPoint(AcGePoint3d(10,10,0));
  postToDb(pDiagonal2, diagonal2ObjId);
  entities.insertAt(0,diagonal2ObjId);

  // use edit target
  ami2DSSetEditTarget(pNewFolder1, pWorkingDb);
  ami2DSGetEditTarget((AmiObjectKey*&)pActiveTarget, pWorkingDb);
  if (pActiveTarget==pNewFolder1) acutPrintf(_ACRX_T("same!\n"));
  amiAddEntitiesToFolder(entities,pActiveTarget);
  ami2DSSetEditTarget(NULL, pWorkingDb);

  return true;
}

// --------------- nesting folders ---------------
Adesk::Boolean nestFolders(
  AmiFolderKey *&pNewFolder1,
  AmiFolderKey *&pNewFolder2,
  AmiFolderDefKey *&pNewFolder3Def,
  AmiFolderKey *&pNewFolder3) {

  AmiFolderKey *pNewFolder4;
  AcDbObjectIdArray entities;
  AcDbObjectId line1ObjId;
  AcDbObjectId circle1ObjId;
  AcDbLine *pDiagonal1 = new AcDbLine();
  AcDbCircle *pCircle1 = new AcDbCircle();

  AcGePoint3d center = AcGePoint3d(30,17.5,0);
  double radius = 5;

  AcDbLine *pLine1 = new AcDbLine();
  AcGeMatrix3d newFolder3GeMatrix;  
  AcGeVector3d newFolder3Translation;
  AcGeMatrix3d newFolder3GeMatrix2;  
  AcGeVector3d newFolder3Translation2;

  // Step 1
  // create circle
  pCircle1->setCenter(center);
  pCircle1->setRadius(radius);
  postToDb(pCircle1, circle1ObjId);
  entities.append(circle1ObjId);

  // create line
  pLine1->setStartPoint(AcGePoint3d(30,17.5,0));
  pLine1->setEndPoint(AcGePoint3d(35,17.5,0));
  postToDb(pLine1, line1ObjId);
  entities.append(line1ObjId);

  // Step 2
  // set translation
  newFolder3Translation.set(30,17.5,0);
  newFolder3GeMatrix.setTranslation(newFolder3Translation);

  // create Folder2 and one instance
  ami2DSCreateFolderDef(
    pNewFolder3Def,
    pNewFolder3,
    entities,
    NULL,
    newFolder3GeMatrix,
    pNewFolder1,
    _ACRX_T("Folder2"));

  // set translation and rotate comp1_2side by 90 degree
  newFolder3Translation2.set(0,0,1);
  newFolder3GeMatrix2.setToRotation((atan(1.0)*2), newFolder3Translation2, AcGePoint3d(0,0,0));
  newFolder3Translation2.set(92.5,30,0);
  newFolder3GeMatrix2.setTranslation(newFolder3Translation2);

  // Step 3
  // add a second instance
  ami2DSInstanceFolder(
    pNewFolder3Def,
    pNewFolder2,
    newFolder3GeMatrix2,
    pNewFolder4);
  
  return true;
}

// --------------- selection modes ---------------
Adesk::Boolean selectionMode(
  AmiFolderKey *&pNewFolder1,
  AmiFolderDefKey *&pNewFolder3Def,
  AmiFolderKey *&pNewFolder3) {

  TCHAR msg[256];
  TCHAR *viewName = nullptr;
  TCHAR *pathName = nullptr;
  AmiPickObj *pPick = new AmiPickObj();
  AmiFolderKey *pPickFolder = NULL;

  struct resbuf* entmask = NULL;
  AmiKeyType pickKeyType=Ami::folderKey;
  amiPick(_ACRX_T("Select folder"), pickKeyType, entmask, *pPick);
  amiGetKeyFromPick(pPick, pickKeyType, (AmiObjectKey *&) pPickFolder);

  ami2DSGetViewName(pPickFolder,viewName);
  ami2DSGetViewGeomPathName(pPickFolder,pathName);

  if(viewName && pathName)
  {
      _stprintf(msg, _ACRX_T("The selected folder's name is '%s'\nIt's full occurrence path is '%s'"), viewName, pathName);
      acutPrintf(msg);
  }

  // --------------- property override ---------------

	// set color override to red
  AcCmColor viewColor;
  viewColor.setColorIndex(1);
  ami2DSSetViewColorOverride(pNewFolder1, true, false, &viewColor) ;
  ami2DSSetViewColorOverride(pNewFolder3, true, false, &viewColor) ;

  // --------------- alter visibility ---------------
  if(AcDbDatabase* pWorkingDb = acdbHostApplicationServices()->workingDatabase())
  {
      // set Folder1:1 to invisible
      amiSetObjectVisibility(pNewFolder1, Adesk::kFalse);


      AmiFolderKey** pNewFolder3Occurences;
      long counter = 0;
      ami2DSGetViewDefOccurrences(pNewFolder3Def, counter, pNewFolder3Occurences, pWorkingDb);

      // set Folder1:1 to visible
      amiSetObjectVisibility(pNewFolder1, Adesk::kTrue);
  }
	
  return true;
}

