/******************************************************************
** Copyright (C) 2001, University of Alabama in Huntsville. 
** All rights reserved.
**
** File   : Instance.cpp
**
** Author : Saranyu Tantipongsakul
**
** Description:
**    This file provides implementation for the CLIPS Instance
**    class.
**
** History:
**    26-Nov-2001 : Saranyu Tantipongsakul
**        Created file.
******************************************************************/

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

#include "Instance.h"

// CCLPInstance Constructor
CCLPInstance::CCLPInstance()
{
    strNameValuePairs = "";
}

// ListInstances for listing all instances
void CCLPInstance::ListInstances()
{
    // List all instances and send them to wdisplay(output)
    Instances("stdout", NULL, NULL, 1);	
}

// Send
void CCLPInstance::Send()
{    
}

// Make Instances in CLIPS
bool CCLPInstance::Make(std::string instanceName, std::string conceptType)
{
    // ===============
    //  Make instance
    // ===============
    // e.g. (make-instance [Block__1]    of CG_CONCEPT_Block    (Marker 1))

    strCommandLine = "";
    strCommandLine.append("(make-instance ");
    strCommandLine.append(instanceName);
    strCommandLine.append(" of ");
    strCommandLine.append(conceptType);
    strCommandLine.append(" ");
    strCommandLine.append(strNameValuePairs);
    strCommandLine.append(")");
    
    //this->routecommand();
    return routecommand();
}

// Unmake for deleting instances
bool CCLPInstance::Unmake(std::string instanceName)
{
    CCLPInstance *ptr;
    
    ptr = CCLPInstance::FindByName(instanceName);
    
    return (bool) (UnmakeInstance(ptr->pClipsInstance) != 0);
    // return non-zero if success, 0 otherwise.
}

// Setvalue for setting up strNameValuePairs
void CCLPInstance::Setvalue(std::string strNameValue)
{
    strNameValuePairs.append("(");
    strNameValuePairs.append(strNameValue);
    strNameValuePairs.append(")" );
}

// FindByName for finding the instance by name
CCLPInstance *CCLPInstance::FindByName(std::string instanceName)
{
    void *ptr;
    
    ptr = FindInstance(NULL, (char *) instanceName.c_str(), true);
    
    if(ptr) {
        CCLPInstance *aInstance = new CCLPInstance();
        aInstance->pClipsInstance = ptr;
        return aInstance;
    }
    else
        throw Instance_Not_Found();
}

// NameOf for finding the name of the instance
std::string CCLPInstance::NameOf()
{
    std::string instanceName;
    
    instanceName = GetInstanceName(this->pClipsInstance);
    return(instanceName);
}

// GetNext for getting next instance
CCLPInstance *CCLPInstance::GetNext(void *pCurrInstance)
{
    void *ptr;
    
    ptr = GetNextInstance(pCurrInstance);
    
    if(ptr) {
        CCLPInstance *pInstance = new CCLPInstance();
        
        pInstance->pClipsInstance = ptr;
        return pInstance;
    }
    else
        throw Instance_Not_Found();   
}

// GetNextInClass for getting next instance in specified class
CCLPInstance *CCLPInstance::GetNextInClass(void *pClass, void *pCurrInstance)
{
    void *ptr;
    
    ptr = GetNextInstanceInClass(pClass, pCurrInstance);
    
    if(ptr) {
        CCLPInstance *pInstance = new CCLPInstance();
        
        pInstance->pClipsInstance = ptr;
        return pInstance;
    }
    else
        throw Instance_Not_Found();
}

// GetChangedStatus for getting the status of the instance
int CCLPInstance::GetChangedStatus()
{
    return GetInstancesChanged();
}

// SetChangedStatus for changing the status of the instance
void CCLPInstance::SetChangedStatus(int status)
{
    SetInstancesChanged(status);
}

// Delete for deleting the specified instances
bool CCLPInstance::Delete()
{
    // Non-zero if successful, 0 otherwise.
    return (bool)(DeleteInstance(pClipsInstance) != 0);	
}

// This function should be called for each external copy of an instance
// address to let CLIPS know that such an outstanding external
// reference exists. As long as an instance's count is greater than zero,
// CLIPS will not release its memory because there may be
// outstanding pointers to the instance. However, the instance can still
// be functionally deleted, i.e. the instance will appear to no longer be
// in the system. The instance address always can be safely passed to
// instance access functions as long as the count for the instance is
// greater than zero. These functions will recognize when an instance
// has been functionally deleted.
void CCLPInstance::IncrementCount(void *instance_ptr)
{
    IncrementInstanceCount(instance_ptr);
}

// This function should only be called to reverse the effects of a
// previous call to IncrementInstanceCount(). As long as an instance's
// count is greater than zero, the memory allocated to it cannot be
// released for other use.
void CCLPInstance::DecrementCount(void *instance_ptr)
{
    DecrementInstanceCount(instance_ptr);
}

// DirGetSlot for storing the value of the specified slot of the specified instance in the
// caller's buffer (the C equivalent of the CLIPS dynamic-get function).
void CCLPInstance::DirGetSlot(void *pInstance, std::string slotName, DATA_OBJECT *result)
{
    DirectGetSlot(pInstance, (char *) slotName.c_str(), result);
}

// DirPutSlot for storing a value in the specified slot of the specified instance (the C 
// equivalent of the CLIPS dynamic-put function).
int CCLPInstance::DirPutSlot(void *pInstance, std::string slotName, DATA_OBJECT *newValue)
{
    // Returns an integer; if zero, an error occurred while setting the slot.
    // If non-zero, no errors occurred.
    return DirectPutSlot(pInstance, (char *) slotName.c_str(), newValue);
}

// GetClass for getting the class name of the instances
CCLPClass *CCLPInstance::GetClass(void *pInstance)
{
	void *ptr;

	ptr = GetInstanceClass(pInstance);

	if(ptr) {
            CCLPClass *pClass = new CCLPClass(ptr);
            return pClass;
	}
	else
            throw Instance_Not_Found();
}


