/******************************************************************
** Copyright (C) 2001, University of Alabama in Huntsville. 
** All rights reserved.
**
** File   : engine.cpp
**
** Author : David Phillips
**
** Description:
**    This file provides a test driver for the CGEngine.
**
** History:
**    24-Nov-2001 : David Phillips
**        Created file.
******************************************************************/

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

#include "CLIPSInterface/Control.h"

#include "CGEngine/CKnowledgeBase.h"
#include "CGEngine/CTypeHierarchy.h"
#include "CGEngine/CTypeDefinition.h"
#include "CGEngine/CRelationHierarchy.h"
#include "CGEngine/CRelationDefinition.h"
#include "CGEngine/CCatalogOfIndividuals.h"
#include "CGEngine/CSheetOfAssertion.h"

#include "CGEngine/ACCGFactory.h"
#include "CGEngine/CCGFactory.h"

#include <iostream>

void TempDriver(ACCGFactory* pFactory, CKnowledgeBase** ppKB)
{
	//std::cout << "Starting..." << std::endl;

    CCLPControl clpcontrol;

    clpcontrol.Initialize();

	// Create Factory
	//   Note:  this will be done by the gui and passed to the parser

	//ACCGFactory* pFactory = new CCGFactory;

	//-- [KnowledgeBase:

	// Creating KnowledgeBase
    //std::cout << "Creating KnowledgeBase" << std::endl;
    CKnowledgeBase* kb = pFactory->NewKnowledgeBase();

	//-- [TypeHierarchy:

	// Creating Type Hierarchy
    //std::cout << "Creating Type Hierarchy" << std::endl;
    CTypeHierarchy* th = pFactory->NewTypeHierarchy();

    kb->SetTypes(th);

	// -- (GT [TypeLabel: "Entity"]
	// --     [TypeLabel: "Block"]
	// --  ; block is an entity ; )

    // Create Type Defintion
	//std::cout << "Creating Type Definition" << std::endl;

	CTypeDefinition* td1 = th->FindByName("Entity");
    
	if (!td1)
	{
		td1 = pFactory->NewTypeDefinition("Entity");
		th->Insert(td1);
	}

	CTypeDefinition* td2 = th->FindByName("Block");
    
	if (!td2)
	{
		td2 = pFactory->NewTypeDefinition("Block");
		th->Insert(td2);
	}

	td2->SetComment("block is an entity");
	td2->AddSuperclass(td1);

    // -- (GT [TypeLabel: "Entity"]
    // --     [TypeLabel: "Location" ]
    // --     ;location is an entity; )

	CTypeDefinition* td3 = th->FindByName("Entity");
    
	if (!td3)
	{
		td3 = pFactory->NewTypeDefinition("Entity");
		th->Insert(td3);
	}

	CTypeDefinition* td4 = th->FindByName("Location");
    
	if (!td4)
	{
		td4 = pFactory->NewTypeDefinition("Location");
		th->Insert(td4);
	}

	td4->SetComment("location is an entity");
	td4->AddSuperclass(td3);

	// Commit Type Hierarchy
	th->Commit();

	// Creating Relation Hierarchy
    //std::cout << "Creating Relation Hierarchy" << std::endl;

    // -- [RelationHierarchy:
	CRelationHierarchy* rh = pFactory->NewRelationHierarchy();

    kb->SetRelations(rh);

    // -- (GT [RelationLabel: "Relation"]
    // --     [RelationLabel: "At"]
    // --     ;New relations - at; )

    CRelationDefinition* rd1 = rh->FindByName("Relation");
	if (!rd1)
	{
		rd1 = pFactory->NewRelationDefinition("Relation");
		rh->Insert(rd1);
	}

    CRelationDefinition* rd2 = rh->FindByName("At");
	if (!rd2)
	{
		rd2 = pFactory->NewRelationDefinition("At");
		rh->Insert(rd2);
	}

	rd2->SetComment("New relations - at");
	rd2->AddSuperclass(rd1);
     
    // -- (GT [RelationLabel: "Relation"]
    // --     [RelationLabel: "OnTable"]
    // --     ;New relations - ontable; )

    CRelationDefinition* rd3 = rh->FindByName("Relation");
	if (!rd3)
	{
		rd3 = pFactory->NewRelationDefinition("Relation");
		rh->Insert(rd3);
	}

    CRelationDefinition* rd4 = rh->FindByName("OnTable");
	if (!rd4)
	{
		rd4 = pFactory->NewRelationDefinition("OnTable");
		rh->Insert(rd4);
	}

	rd4->SetComment("New relations - ontable");
	rd4->AddSuperclass(rd3);

	// Commit Relation Hierarchy
	rh->Commit();

	// Creating Catalog Of Individuals

    //std::cout << "Creating COI" << std::endl;

    // -- [CatalogOfIndividuals:
    
	CCatalogOfIndividuals* coi = pFactory->NewCatalogOfIndividuals();

    kb->SetCOI(coi);

    // -- [Block:#1] [Location:#5]

	// For [Block:#1]
	CTypeDefinition *pTypeDef1 = th->FindByName("Block");

	if (!pTypeDef1)
	{
		pTypeDef1 = pFactory->NewTypeDefinition("Block");
		th->Insert(pTypeDef1);
		pTypeDef1->Commit();
	}

    CConcept *con1 = pFactory->NewConcept();
    con1->SetName("");   // Need to check for name in COI area
	con1->SetTypeDef(pTypeDef1);
	con1->SetIndividualMarker("#1");
    coi->Insert(con1);

    // For [Location:#5]
	CTypeDefinition *pTypeDef2 = th->FindByName("Location");

	if (!pTypeDef2)
	{
		pTypeDef2 = pFactory->NewTypeDefinition("Location");
		th->Insert(pTypeDef2);
		pTypeDef2->Commit();
	}

    CConcept *con2 = pFactory->NewConcept();
    con2->SetName("");
	con2->SetTypeDef(pTypeDef1);
	con2->SetIndividualMarker("#5");
    coi->Insert(con2);
	
	// Creating Sheet Of Assertion
    //std::cout << "Creating Sheet Of Assertion" << std::endl;

    
    // -- [Assertion:

	CSheetOfAssertion* soa = pFactory->NewSheetOfAssertion();

    kb->SetSOA(soa);

    // -- (ATTR [Block:#1] [Color:'Red'] ;Block #1 is red;)
    // -- (OnTable [Block:#1] [Location:#5])
    CRelationDefinition *pRelType = rh->FindByName("ATTR");

	if (!pRelType)
	{
		pRelType = pFactory->NewRelationDefinition("ATTR");
		rh->Insert(pRelType);
		pRelType->Commit();
	}
    
	CRelation *rel1 = pFactory->NewRelation();
    rel1->SetRelDef(pRelType); // Temporarily added by Satish

    CConcept* arc1 = coi->FindByMarker("#1");
    soa->Insert(arc1);
	rel1->AddArc(arc1);

	// second arc
	CTypeDefinition *pArcType2 = th->FindByName("Color");

	if (!pArcType2)
	{
		pArcType2 = pFactory->NewTypeDefinition("Color");
		th->Insert(pArcType2);
		pArcType2->Commit();
	}

    CConcept *arc2 = pFactory->NewConcept();
    arc2->SetName("Red");
	arc2->SetTypeDef(pArcType2);
    soa->Insert(arc2);
	rel1->AddArc(arc2);

    soa->Insert(rel1);
	
	/*
    // Some more testing
	//std::cout << "Finding By UID" << std::endl;
	ACConstruct* construct1 = ACConstruct::FindByUid(5);

	//std::cout << "Opening CLIPS shell" << std::endl;
    clpcontrol.shell();

	//std::cout << "Finished!!!" << std::endl;

	exit (0);
    */
    *ppKB = kb;
}