#pragma warning(disable: 4786)  // Disable debug information warning

extern "C" 
{
  #include "clips/clips.h"
}

#include "Control.h"
#include "Class.h"
#include "Instance.h"

int main(void)
{
    int run_level;
    
    CCLPControl clpcontrol;

    /* high level control the behavior of clips core */
    clpcontrol.Initialize();
    clpcontrol.load("SampleData/input.clip");
    CCLPClass *test1;
    test1 = CCLPClass::FindByName("CG_CONCEPT");

	std::cout << "isAbstract is " << test1->IsAbstract() << std::endl;

    CCLPClass *test2;

    test2 = CCLPClass::FindByName("CG_CONCEPT_Block");

    std::cout << "isAbstract is " << test2->IsAbstract() << std::endl;

    CCLPClass *test3 = new CCLPClass;
	test3->SetName("ATestClass");
	test3->AddSlot("SomeData");
	test3->Define("USER");

    // ======================
    //  Test CLIPS Instances
    // ======================
    
    // Test to list all instances
    std::cout << "Test to list all instances" << std::endl;
	
    CCLPInstance::ListInstances();
    
    // Test to unmake instance [Block__1]
    std::cout << "Test to unmake instance [Block__1]" << std::endl;

    CCLPInstance::Unmake("Block__1");    
    CCLPInstance::ListInstances();
    
    // Test to make-instance [Block__100]
    std::cout << "Test to make-instance [Block__100]" << std::endl;
	std::string nameValue, instanceName, conceptType;

    nameValue.append("Marker 100");
    instanceName.append("Block__100");
    conceptType.append("CG_CONCEPT_Block");

    CCLPInstance *myInstance = new CCLPInstance();

    myInstance->Setvalue(nameValue);
    myInstance->Make(instanceName, conceptType);
    
    CCLPInstance::ListInstances();
    getchar();

    // Test to get next instance from [Block_100]
    std::cout << "Test to get next instance from [Block_100]" << std::endl;
    std::string newName;
    CCLPInstance *aInstance;
    CCLPInstance *nextInstance;

    newName.append("Block__2");
    aInstance = CCLPInstance::FindByName(newName);

    std::cout << "Current instance is " << aInstance->NameOf() << std::endl;

    nextInstance = aInstance->GetNext(aInstance->pClipsInstance);
    std::cout << "Next instance is " << nextInstance->NameOf() << std::endl;
    getchar();

    // Test Get/Set InstanceChanged
    std::cout << "Test Get/Set InstanceChanged" << std::endl;
    std::cout << "Changes of " << aInstance->NameOf()
         << " is " << aInstance->GetChangedStatus() << std::endl;
    
    aInstance->SetChangedStatus(0);

    std::cout << "Changes of " << aInstance->NameOf()
         << " is " << aInstance->GetChangedStatus() << std::endl;

    getchar();

    // Test Delete Instance [Block__2]
    std::cout << "Test Delete Instance [Block__2]" << std::endl;

    aInstance->Delete(aInstance->pClipsInstance);
    CCLPInstance::ListInstances();
    getchar();

    // Test to get Class of the instance
    std::cout << "Test to get Class of the instance" << std::endl;
    CCLPClass *aClass;
    
    newName.assign("Hand__1");
    aClass = CCLPInstance::GetClass((CCLPInstance::FindByName(newName))->pClipsInstance);

    std::cout << "Class of " << newName << " is " << GetDefclassName(aClass->GetDefClass()) << std::endl;
	
    getchar();
    
    // Test to get next instance in test2 class [CG_CONCEPT_Block] 
    std::cout << "Test to get next instance in test2 class " << std::endl;
    
    aInstance = CCLPInstance::GetNextInClass(test2->GetDefClass(), NULL);	// Get the first instance
    std::cout << "First Instance is " << aInstance->NameOf() << std::endl;

    // Get the next instance
    aInstance = CCLPInstance::GetNextInClass(test2->GetDefClass(), aInstance->pClipsInstance);	
    std::cout << "Next Instance is " << aInstance->NameOf() << std::endl;


    run_level = clpcontrol.run(-1L);
    std::cout << "run level: " << run_level << std::endl;
    clpcontrol.shell();
    
    return 0;
}


