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

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

#include "Class.h"
#include <iostream>
extern "C" 
{
  #include "clips/clips.h"
}

// CCLPClass Constructor
CCLPClass::CCLPClass()
{
	m_pDefClass = NULL;
}

CCLPClass::CCLPClass(void* pDefClass)
{
	m_pDefClass = pDefClass;
}

// FindByName for finding the class by name
CCLPClass* CCLPClass::FindByName(std::string className)
{
    void *pDefClass;
    
    pDefClass = FindDefclass((char*)className.c_str());

    if (pDefClass)
    {
        CCLPClass *pCCLPClass = new CCLPClass;
        pCCLPClass->m_pDefClass = pDefClass;
		pCCLPClass->m_sName = className;

        return pCCLPClass;
    }
    else
    {
        throw Class_Not_Found();
    }
    
}

// AddSlot for adding slot to create class
void CCLPClass::AddSlot(std::string str)
{
    m_slots.push_back(str);
}

// DeleteSlot for deleting slot
void CCLPClass::DeleteSlot(std::string str)
{
}

// IsAbstract for determining if a class is concrete or abstract
bool CCLPClass::IsAbstract()
{
    return (bool)(ClassAbstractP(this->m_pDefClass) == 1);
}

// BrowseClass for printing a graph of all classes which inherit 
// from the specified class.
void CCLPClass::BrowseClass()
{
    BrowseClasses("stdout", this->m_pDefClass);
}

// ListDefClass for printing the list of defclasses
void CCLPClass::ListDefClass()
{
    ListDefclasses("stdout", NULL);		// list all defined class: NULL pointer
}

// Describe for printing a summary of the specified class including: abstract/concrete
// behavior, slots and facets (direct and inherited) and recognized
// message-handlers (direct and inherited).
void CCLPClass::Describe() 
{
    DescribeClass("stdout", this->m_pDefClass);
}

// Groups the names of slots of a class into a multifield data object.
DATA_OBJECT CCLPClass::GetSlots()
{
    DATA_OBJECT clipsResult;

    ClassSlots(this->m_pDefClass, &clipsResult, 1);
    /* 1: get all slot including the inherited from superclass,
       0: only explicit slots defined in this class
    */
    return clipsResult;
}

// GetDefClass for getting the pointer to class
void* CCLPClass::GetDefClass()
{
	return m_pDefClass;
}

// Groups the names of subclasses of a class into a multifield data
// object.
DATA_OBJECT CCLPClass::SubClass()
{
    DATA_OBJECT clipsResult;

    ClassSubclasses(this->m_pDefClass, &clipsResult, 0);
    /* 1: get all slot including the inherited from superclass,
       0: only explicit slots defined in this class
    */
    return clipsResult;
}

// Groups the names of superclasses of a class into a multifield data
// object.
DATA_OBJECT CCLPClass::SuperClass()
{
    DATA_OBJECT clipsResult;

    ClassSuperclasses(this->m_pDefClass, &clipsResult, 0);
    /* 1: get all slot including the inherited from superclass,
       0: only explicit slots defined in this class
    */
    return clipsResult;
}

// NameOf for getting the name of this class
std::string CCLPClass::NameOf()
{
	std::string className;
        
    className = GetDefclassName(this->m_pDefClass);
    return className;
}

// IsDeletable for indicating whether or not a particular class and 
// all its subclasses can be deleted.
bool CCLPClass::IsDeletable()
{
    return (bool) (IsDefclassDeletable(this->m_pDefClass) == 1);
}

// IsSubClass for determining if a class is a subclass of another class.
bool CCLPClass::IsSubClass(std::string className)
{
    void *pDefClass;
    
    pDefClass = FindDefclass((char*)className.c_str());
    if(pDefClass)
        return (bool)(SubclassP(this->m_pDefClass, pDefClass) == 1);
    else return FALSE;
}

// IsSuperClass for determining if a class is a superclass of another class.
bool CCLPClass::IsSuperClass(std::string className)
{
    void *pDefClass;
    
    pDefClass = FindDefclass((char*)className.c_str());
    if(pDefClass)
        return (bool)(SuperclassP(this->m_pDefClass, m_pDefClass) == 1);
    else return FALSE; 
}

// SetName for setting the name of class to create
void CCLPClass::SetName(std::string sName)
{
	m_sName = sName;
}

// Define for creating the class
void CCLPClass::Define(std::string superClass)
{
	/*	(defclass CG_CONCEPT  (is-a USER)
            (slot Name   (create-accessor read-write))
            (slot Marker (create-accessor read-write)) ) */

	strCommandLine = "(defclass ";
	strCommandLine.append(m_sName);
	strCommandLine.append(" (is-a ");
	strCommandLine.append(superClass);
	strCommandLine.append(") (role concrete)\n");

	// iterate slots
	slot_vector_type::iterator iterSlot;
    iterSlot = m_slots.begin();

	while (iterSlot != m_slots.end())
	{
		strCommandLine.append ("(slot ");
		strCommandLine.append (*iterSlot);
        strCommandLine.append ("(create-accessor read-write))\n");
		iterSlot++;
	}

	strCommandLine.append(")");

	std::cout << "Define using:  " << std::endl << strCommandLine << std::endl;
	routecommand();

    m_pDefClass = FindDefclass((char*)m_sName.c_str());

}
