// COPYRIGHT DASSAULT SYSTEMES 2000
// COPYRIGHT ANSYS/ICEMCFD 2003-2005
//=============================================================================
// Abstract of the use case "CAAniCatalog":
// ---------------------------------------
//
// This use case illustrates how to create a new StartUp catalog, how to create
// a StartUp that derives from a previously created StartUp, and how to manage
// attributes related to the StartUps.
//
// A StartUp is an initial feature definition. It describes a data structure
// containing a feature and one or more attributes. From the StartUp "mold",
// new features can be created by instantiation. New attributes can be added
// to these instantiated features. StartUps must be created in catalogs. 
// Creating StartUps is the first step to working with features.
//=============================================================================
//
// The ICCGatewayCatalog.CATfct catalog is first created, in which a StartUp with
// name and type set to CFDDynamicSet is created, that derives from the
// SolutionSet StartUp defined in the AnalysisModeler.feat StartUp catalog.
// In the CFDDynamicSet Startup, attribute management include:  
//	- Assign a value to the attribute PhysicalType inherited from SolutionSet
//	- Create an attribute as a BasicComponent in order to reference the solution file

//=============================================================================
//  Main Methods:
//  ------------ 
//
//  Create_Session     Creates a new session, necessary in a batch program
//  CreateCatalog      Creates a new catalog for storing StartUps
//  SetClientId        Sets a client identification name for the catalog: all 
//                     StartUp names will have this id added as a suffix
//  OpenCatalog        Opens an existing StartUp catalog
//  RetrieveSU         ????? Is it necessary ???????
//  CreateSUInCatalog  Creates a new StartUp
//  GetAttrKey         Returns a key to access an exsting attribute
//  SetString          Assigns a value to an attribute    
//  AddAttribute       Adds an attribute to a StartUp
//  GetDocument        Retrieves the CATDocument pointer given a CATILinkable
//                     pointer onto the catalog in order to be able to save it
//  Save               Saves the catalog document
//  Remove             Removes the catalog document from the session
//  Delete_Session     Deletes the session
//
//=============================================================================
//  Return Errors:
//  -------------
//  1 - ERROR in managing the session
//  2 - ERROR in managing catalog
//  3 - ERROR in Managing StartUp
//  4 - ERROR in QueryInterface
//  5 - ERROR in Spec Objects
//
//  Running the program:
//  -------------------
//  To run this program, use the command:
//        mkrun -c "CAAniCatalog CatalogStorageName" 
//  where the "CatalogStorageName" is the entire pathname of the current workspace
//  + os_directory + resources + graphic + CatalogName.
//  For example, under 
//  Windows, the "CatalogStorageName" would be:
//        currentWS\intel_a\resources\graphic\ICCGatewayCatalog
//  or under AIX:
//        currentWS/aix_a/resources/graphic/ICCGatewayCatalog
//         
//=============================================================================

// ICCBase Framework
#include "ICCCatalogServices.h"

// System Framework
#include "CATUnicodeString.h"
#include "CATLib.h"

//ObjectModelerBase Framework
#include "CATSessionServices.h"          // Create_Session and Delete_Session
#include "CATDocumentServices.h"         // SaveAs, Remove catalog 
#include "CATDocument.h"                 // GetDocument
#include "CATInit.h"                     // GetRootContainer
#include "CATIContainer.h"               // CreateCatalog output

//ObjectSpecsModeler Framework
#include "CATCatalogFactoryServices.h"   // CreateCatalog global function
#include "CATICatalog.h"                 // CreateSUInCatalog, SetClientId
#include "CATISpecObject.h"              // AddAttribute
#include "CATISpecAttribute.h"           // Result of AddAttribute
#include "CATISpecAttrAccess.h"
#include "CATISpecAttrKey.h"

// AnalysisCatalog methods.
#include "CATSamCatalogFactory.h"        // Access to Analysis Catalog tools
#include "CATSamDefs.h"

#include "CATISamAnalysisSet.h"
#include "CATISamBasicComponent.h"
#include "CATISamAnalysisSupport.h"

//Literal
#include "CATICkeParmFactory.h"
#include "CATIEnumere.h"
#include "CATICkeParm.h"
#include "CATIParmDictionary.h"

// CATIA V5 build level ( needed for Depricated API see CATIAV5R12 )
#include "CATIAV5Level.h"

//Other includes
#include <iostream.h>


int main (int argc, char * argv[] )
{ 
    //====================================================================
    //
    // -1- Creating a path to the catalog.
    // 
    //  o  "main" first argument is directory path : to use your catalog,
    //     it should be located under resources\graphic directory.
    //
    //  o  Catalog file name is set to ICCBlockingCatalog.
    //
    //     CATMakePath of CATLib.h creates an os dependant path.
    //
    //====================================================================
    
    cout << "-1- Creating a path to the catalog." << endl << flush;
    
    const char *pDirName;
    if ( argc < 2)
	{
	    cout << "    Warning  : no directory path given. Using current dir." << endl;
	    pDirName = ".";
	} else {
	    pDirName = argv[1];
	}
    
    const char *pFileName    = "ICCGatewayCatalog.CATfct";
    char       StorageName[200];
    
    CATMakePath( pDirName , pFileName , StorageName );
  
    
    //======================================================================
    // Creating a session.
    //======================================================================
     
    cout << "    Creating a session." << endl << flush;
    
    const char *pSessionName = "ICEMCFD/ANSYS Gateway";
    CATSession *pSession     = NULL;
    
    HRESULT rc = Create_Session( (char *) pSessionName , pSession );
    
    if ( SUCCEEDED(rc) )
        cout << "    Session creation OK." << endl << flush;
    else
	{
	    cout << "    ERROR in creating the session." << endl << flush;
	    return 1;
	}
    
    
    //=======================================================================
    // Create a catalog:  CreateCatalog uses argv[1] as pathname
    //=======================================================================
    CATICatalog *piCatalog = NULL;
    CATUnicodeString storageName = "ICCGatewayCatalog.CATfct";
    rc = ::CreateCatalog(&storageName,&piCatalog);
    if (NULL == piCatalog) 
	{
	    cout << "ERROR in creating Catalog" << endl << flush;
	    cout << "Workspace/ToolsData/Msdev/framework/"<<storageName<<endl;
	    cout << "already exists, remove it" << endl << flush;
	    return 2;
	}
    else cout << "Catalog created OK " << endl << flush;	

    // Add a client identification to the catalog.  This is a mandatory step. 

    CATUnicodeString clientId("ICCGatewayCatalog");
    rc = piCatalog -> SetClientId(&clientId);
    if (NULL == rc) cout << "ClientID setOK" << endl << flush;
    else cout << "ERROR in setting ClientID" << endl << flush;

    //=====================================================================
    // Create the CFDDynamicSet StartUp within the ICCGatewayCatalog catalog.
    // Do not forget to release the interface pointers when they are no
    // longer needed.  The created StartUp is assigned its name and type as
    // CFDDynamicSet, and derives from the SolutionSet StartUp of
    // AnalysisModeler.feat In the created Startup, 
    //   - Assign a value to the attribute PhysicalType (solution/restraint)
    //	 - Create new attribute ExternalFile (reference the solution File)
    //=====================================================================
    
    CATBoolean publicSpec = TRUE;
    CATBoolean derivable = TRUE;
    CATBaseUnknown *pCFDSU = NULL;
    CATBaseUnknown *pCFDRESTRAINTSU = NULL;
    CATUnicodeString CFDSUType("ICCGatewaySet");
    CATUnicodeString CFDRESTRAINTType("ICCGatewayRestraintSet");
    CATUnicodeString SolutionSUType("SolutionSet");
    CATUnicodeString RestraintSUType("RestraintSet");

    rc = CATSamCatalogFactory::CreateAnalysisSet (&CFDSUType,
						  &SolutionSUType,
						  &pCFDSU,
						  &piCatalog,
						  publicSpec,
						  derivable);
    
    rc = CATSamCatalogFactory::CreateAnalysisSet (&CFDRESTRAINTType,
						  &RestraintSUType,
						  &pCFDRESTRAINTSU,
						  &piCatalog,
						  publicSpec,
						  derivable);

    if (NULL == pCFDSU) {
	cout << "ERROR in creating CFDDynamic StartUp" << endl << flush;
	if (piCatalog) piCatalog -> Release(); 
	piCatalog = NULL;
	return 3;
    }
    else cout << "CFDDynamicSet StartUp created OK" << endl << flush;

// Valuate PhysicalType attribute
    CATUnicodeString PType("CFD_SOLUTION");
    CATUnicodeString PRestraintType("RESTRAINT");
#if defined ( CATIAV5R13 )
    // CATSamCatalogFactory::SetPhysicalType (pCFDSU, &PType);
    CATSamCatalogFactory::SetPhysicalType (pCFDRESTRAINTSU, &PRestraintType);
#else
    CATSamCatalog_SetPhysicalType (pCFDSU, &PType);
    CATSamCatalog_SetPhysicalType (pCFDRESTRAINTSU, &PRestraintType);
#endif

    // Define  ExternalFile attribute 
    CATUnicodeString NewBCType("ICCGatewayFileLink");
    CATUnicodeString DeriveBCType("SAMBCFileAccess");
    CATBaseUnknown * piOut = NULL;
#if defined ( CATIAV5R13 )
    CATSamCatalogFactory::CreateBasicComponent (&NewBCType,&DeriveBCType,&piOut,&piCatalog);
#else
    CATSamCatalog_BasicComponent (&NewBCType,&DeriveBCType,&piOut,&piCatalog);
#endif
    if (piOut) {
	CATISamBasicComponent_var spComponent(piOut);
	if (!!spComponent) {
	    spComponent -> SetStringValue("cgns;uns;cas;tec;tecp;rfl;dmp","LinkType");
	}
	piOut -> Release();
    }

    CATISamAnalysisSet *piAnalysisSet =NULL;
    pCFDSU -> QueryInterface(IID_CATISamAnalysisSet,(void **)& piAnalysisSet);
    if (piAnalysisSet) {
	piAnalysisSet -> AddBasicComponent("ICCGatewayFileLink","ICCGatewayFileLink");
	piAnalysisSet -> Release();
    }

    CATISpecAttribute * Attribute = NULL;
    CATISpecObject *psoCFDSU = (CATISpecObject *) pCFDSU;
    Attribute = psoCFDSU->AddAttribute("ICCGatewayFileExt", tk_string, sp_NEUTRAL);
    if (Attribute) Attribute->Release();
    Attribute = NULL;

    Attribute = psoCFDSU->AddAttribute("ICCGatewayFileLine", tk_string, sp_NEUTRAL);
    if (Attribute) Attribute->Release();
    Attribute = NULL;

    pCFDSU -> Release(); pCFDSU=NULL;

    //======================================================================
    // MeshPart to store the imported mesh
    //======================================================================

    CATBaseUnknown *pMpCFDSU = NULL;
    CATUnicodeString MPType("ICCGatewayMeshPart");
#if defined ( CATIAV5R13 )
    rc = CATSamCatalogFactory::CreateMSHPart (&MPType,&pMpCFDSU,&piCatalog,publicSpec,derivable);
#else
    rc = CATSamCatalog_MSHPart (&MPType,&pMpCFDSU,&piCatalog,publicSpec,derivable);
#endif

    if (NULL == pMpCFDSU) 
	{
	    cout << "ERROR in creating Mesh Part StartUp" << endl << flush;
	    if (piCatalog) piCatalog -> Release();
	    piCatalog = NULL;
	    return 3;
	}

    cout << "Mesh Part StartUp created OK" << endl << flush;
    CATISpecObject *piMshMart = (CATISpecObject*) pMpCFDSU;
    if ( NULL != piMshMart)
	{
	    Attribute = piMshMart->AddAttribute("InputLink",tk_specobject,sp_IN);
	    if (Attribute) Attribute-> Release();
	    Attribute = NULL;

	    Attribute = piMshMart->AddAttribute("FileLine", tk_string, sp_IN);
	    if (Attribute) Attribute->Release();
	    Attribute = NULL;
	}
    if (pMpCFDSU) pMpCFDSU -> Release();
    pMpCFDSU = NULL;

    //=====================================================================
    // Create An Analysis Entity by derivation of AnalysisRestraint.
    // This entity is made of a 3D SPEED Vector
    // This entity will appear under the restraint Set Definition. It will be
    // applied on a 3D body.
    //=====================================================================
    
    CATICkeParmFactory_var spCkeFact = NULL_var;
    CATILinkableObject * piLinkableOnCatalogTmp1 = NULL;
    rc = piCatalog->QueryInterface(IID_CATILinkableObject,
				   (void**) &piLinkableOnCatalogTmp1);
    if(SUCCEEDED(rc) && piLinkableOnCatalogTmp1 != NULL) {

	CATDocument * pCDocTmp1 = piLinkableOnCatalogTmp1->GetDocument();
	piLinkableOnCatalogTmp1->Release(); 
		
	CATInit_var spInit1 = pCDocTmp1;
	CATIContainer_var spRootContTmp1 = (CATIContainer*)spInit1->GetRootContainer("CATIContainer");
	spCkeFact = spRootContTmp1;
    }
    
    if (spCkeFact != NULL_var) {
	CATISamAnalysisSupport_var spSupport = NULL_var;
	CATISpecObject_var spObj = NULL_var;
	CATISpecAttrAccess_var spObjAccess = NULL_var;
	CATISpecAttrKey_var spObjKey = NULL_var;
	CATISamBasicComponent_var spComp = NULL_var;
	CATICkeParm_var spParm = NULL_var;
	CATICkeParm     *pParm = 0;
	static CATUnicodeString labels[128];
	size_t nlabels = 0;
	
	CATBaseUnknown *pNextEntity = 0, *pNextField=0, *pAggrField=0;
	CATUnicodeString nextName, nextCompName, nextRestraintName, nextSU;
	CATUnicodeString nextPhysType, nextFieldName;
	CATUnicodeString AnalRestraint("AnalysisRestraint");
	
__BCS__
    }
    
    //======================================================================
    // Create An Analysis Entity by derivation of AnalysisRestraint.
    // This entity is made of Basic Component that allow to select a
    // Dynamic solution.  This entity will appear under the restraint
    // Set Definition.
    //======================================================================
    // Defines a Basic component that is a derivation of SamSingleEntityPtr
    // Defines the DymanicSet As selectable in the Same Fem Model
    // (Same topology)
    //----------------------------------------------------------------------
    CATUnicodeString BcPtrSUType ="SAMSingleEntityPtr";
    CATBaseUnknown *pBcPtrSU = NULL;
    CATUnicodeString BcType("CFDPtrOnSolution");
#if defined ( CATIAV5R13 )
    rc = CATSamCatalogFactory::CreateBasicComponent (&BcType,&BcPtrSUType,&pBcPtrSU,&piCatalog);
#else
    rc = CATSamCatalog_BasicComponent (&BcType,&BcPtrSUType,&pBcPtrSU,&piCatalog);
#endif
    if (NULL == pBcPtrSU) 
	{
	    cout << "ERROR in creating"<<BcType.ConvertToChar() <<" StartUp" << endl << flush;
	    if (piCatalog) piCatalog -> Release();
	    piCatalog = NULL;
	    return 3;
	}

    CATISpecAttribute*	pAttribute = ((CATISpecObject*)pBcPtrSU) -> GetAttribute ("Neighbourhood");
    if (NULL != pAttribute)
	{
	    pAttribute -> SetInteger((int)Neighbourhood_SameFemModel);
	    pAttribute -> Release();
	    pAttribute = NULL;
	}
    pAttribute = ((CATISpecObject*)pBcPtrSU) -> GetAttribute ("AllowedFeatType");
    if (NULL != pAttribute)
	{
	    pAttribute -> SetString("Any");
	    pAttribute -> Release();
	    pAttribute = NULL;
	}

    pAttribute = ((CATISpecObject*)pBcPtrSU) -> AddAttribute ("Values",tk_specobject,sp_IN);
    if (NULL != pAttribute)
	{
	    pAttribute -> Release();
	    pAttribute = NULL;
	}

    // Defines an analysis entity that is a derivation of Analysis Restraint.
    //------------------------------------------------------------
    CATUnicodeString PtrSUEntity ="AnalysisRestraint";
    CATBaseUnknown *pPtrEntity = NULL;
    CATUnicodeString EntiP("CFDEntityOnSolution");
#if defined ( CATIAV5R13 )
    rc = CATSamCatalogFactory::CreateAnalysisEntity (&EntiP,&PtrSUEntity,&pPtrEntity,&piCatalog);
#else
    rc = CATSamCatalog_AnalysisEntity (&EntiP,&PtrSUEntity,&pPtrEntity,&piCatalog);
#endif
    if (NULL == pPtrEntity) 
	{
	    cout << "ERROR in creating"<<EntiP.ConvertToChar() <<" StartUp" << endl << flush;
	    if (piCatalog) piCatalog -> Release();
	    piCatalog = NULL;
	    return 3;
	}

    PType = "GENERIC_ENTITY";
#if defined ( CATIAV5R13 )
    CATSamCatalogFactory::SetPhysicalType (pPtrEntity, &PType);
#else
    CATSamCatalog_SetPhysicalType (pPtrEntity, &PType);
#endif

    // Associates the Basic component to the entity.
    //------------------------------------------------------------
#if defined ( CATIAV5R13 )
    CATSamCatalogFactory::SetBasicComponent (&BcType,pPtrEntity,&piCatalog);
#else
    CATSamCatalog_SetBasicComponent (&BcType,pPtrEntity,&piCatalog);
#endif
    if (pBcPtrSU)    pBcPtrSU-> Release();
    pBcPtrSU = NULL;
    if (pPtrEntity)  pPtrEntity-> Release();
    pPtrEntity = NULL;

    //===============================================================================
    // Save the catalog and delete the session.
    //===============================================================================

    if (piCatalog)
	{
	    rc = ::SaveCatalog(&piCatalog,&storageName);
	    if (piCatalog) piCatalog -> Release();
	    piCatalog = NULL;
	}

    if (FAILED(rc))
	{
	    cout << "ERROR in saving catalog document" << endl << flush;
	    return 2;
	}

			
    cout << "Created: " << storageName << endl;

// Delete session
    rc = ::Delete_Session((char *) pSessionName);
    if (FAILED(rc))
	{
	    cout << "ERROR in deleting session" << endl << flush;
	    return 1;
	}
			
    return 0;
  
}
