/******************************************************************************
** Copyright (C) 2001, University of Alabama in Huntsville. All rights 
** reserved.
**
** File   : DrawableSOA.cpp
**
** Author : Satish Hota
**
** Description:
**    This file provides implementation for CDrawableSOA class.
**
** History:
** 28-Nov-01 Satish Hota
**     File Created. 
** 28-Nov-01 Satish Hota
**    Added Draw method.
** 01-Dec-01 Satish Hota
**     Implemented the Draw method.  Added and implemented the ObjectsAt 
**     method.
** 02-Dec-01 Satish Hota
**     Modified the Draw method to draw arcs between relations and concepts.
******************************************************************************/

#include "stdafx.h"
#include "ConGraT.h"
#include "DrawableSOA.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDrawableSOA::CDrawableSOA()
{

}

CDrawableSOA::~CDrawableSOA()
{

}

long CDrawableSOA::Draw()
{
    CConcept::ConceptVector::iterator iterConcepts;
    CRelation::RelationVector::iterator iterRelations;
    CDrawable *pDrawable;
    bool bFirst = true;
	
    // Draw all concepts
    for(iterConcepts = m_vectorConcept.begin();iterConcepts != m_vectorConcept.end();iterConcepts++)
    {
		pDrawable = dynamic_cast<CDrawable*>(*iterConcepts);
        if(!pDrawable)
        {
            ASSERT(0);
            continue;
        }
        else
        {
            pDrawable->Draw();
            if(bFirst)
            {
                pDrawable->GetFromLocation(&m_nFromX, &m_nFromY);
                pDrawable->GetToLocation(&m_nToX, &m_nToY);
                bFirst = false;
            }
            else
            {
                CRect curRect(m_nFromX, m_nFromY, m_nToX, m_nToY);
                int x1, y1, x2, y2;
                pDrawable->GetFromLocation(&x1, &y1);
                pDrawable->GetToLocation(&x2, &y2);
                CRect newRect(x1, y1, x2, y2);
                curRect.UnionRect(curRect, newRect);
                m_nFromX = curRect.left;
                m_nFromY = curRect.top;
                m_nToX = curRect.right;
                m_nToY = curRect.bottom;
            }
        }
    }

    // Draw all relations
    for(iterRelations = m_vectorRelation.begin();iterRelations != m_vectorRelation.end();iterRelations++)
    {
		pDrawable = dynamic_cast<CDrawable*>(*iterRelations);
        if(!pDrawable)
        {
            ASSERT(0);
            continue;
        }
        else
        {
            pDrawable->Draw();
            if(bFirst)
            {
                pDrawable->GetFromLocation(&m_nFromX, &m_nFromY);
                pDrawable->GetToLocation(&m_nToX, &m_nToY);
                bFirst = false;
            }
            else
            {
                CRect curRect(m_nFromX, m_nFromY, m_nToX, m_nToY);
                int x1, y1, x2, y2;
                pDrawable->GetFromLocation(&x1, &y1);
                pDrawable->GetToLocation(&x2, &y2);
                CRect newRect(x1, y1, x2, y2);
                curRect.UnionRect(curRect, newRect);
                m_nFromX = curRect.left;
                m_nFromY = curRect.top;
                m_nToX = curRect.right;
                m_nToY = curRect.bottom;
            }
        }
    }

    /***** Not yet implemented by Engine *********************
    // Draw All arcs

    CDrawableArc oDrawableArc;
    CDrawableElement *pDrawableElement;
    CRelation* pRelation;
    ConceptVector *pConceptVector;
    ConceptVector::const_iterator iterConstConcepts;
    CConcept*  pConcept, pSecondaryConcept;

    // Draw co-referent arcs
    oDrawableArc.SetLineEndType(CDrawableLine::LineEndType_Default);
	oDrawableArc.SetLineType(CDrawableLine::LineType_Dashed);
    for(iterConcepts = m_vectorConcept.begin();iterConcepts != m_vectorConcept.end();iterConcepts++)
    {
		pConcept = dynamic_cast<CConcept*>(iterConcepts);
        if(!pConcept)
        {
            ASSERT(0);
            continue;
        }
        // If this concept is not the one that is the primary concept,
        // do  not draw arcs.  This is to prevent multiple arcs from being drawn.
        if(!pConcept->IsDefLabel())
            continue;

        pConceptVector = pConcept->get_coreferent_set();
        for(iterConstConcepts = pConceptVector->begin(); iterConstConcepts != pConceptVector->end();iterConstConcepts++)
        {
            pSecondaryConcept = dynamic_cast<CConcept*>(*iterConstConcepts);
            if(!pSecondaryConcept)
            {
                ASSERT(0);
                continue;
            }

			pDrawableElement = dynamic_cast<CDrawableElement*>(pConcept);
            oDrawableArc.SetFromObject(pDrawableElement);
            pDrawableElement = dynamic_cast<CDrawableElement*>(pSecondaryConcept);
            oDrawableArc.SetToObject(pDrawableElement);

            oDrawableArc.Draw();
        }
    }
    ***** Not yet implemented by Engine *********************/
    CDrawableArc oDrawableArc;
    CDrawableElement *pDrawableElement;
    CRelation* pRelation;
    const CConcept::ConceptVector *pConceptVector;
	CConcept::ConceptVector::const_iterator constIterConcepts;
    CConcept*  pConcept;

    oDrawableArc.SetLineEndType(CDrawableLine::LineEndType_EndArrow);
	oDrawableArc.SetLineType(CDrawableLine::LineType_Solid);
    for(iterRelations = m_vectorRelation.begin();iterRelations != m_vectorRelation.end();iterRelations++)
    {
        pRelation = dynamic_cast<CRelation*>(*iterRelations);
        if(!pRelation)
        {
            ASSERT(0);
            continue;
        }
        
        // Draw all arcs from originating concepts
        pConceptVector = pRelation->GetFromArcs();
        for(constIterConcepts = pConceptVector->begin(); constIterConcepts != pConceptVector->end();constIterConcepts++)
        {
            pConcept = dynamic_cast<CConcept*>(*constIterConcepts);
            if(!pConcept)
            {
                ASSERT(0);
                continue;
            }

			pDrawableElement = dynamic_cast<CDrawableElement*>(pConcept);
            oDrawableArc.SetFromObject(pDrawableElement);
            pDrawableElement = dynamic_cast<CDrawableElement*>(pRelation);
            oDrawableArc.SetToObject(pDrawableElement);

            oDrawableArc.Draw();
        }

        // Draw arc to terminating concept
        pConcept = pRelation->GetToArc();
        if(!pConcept)
        {
            ASSERT(0);
            continue;
        }

		pDrawableElement = dynamic_cast<CDrawableElement*>(pRelation);
        oDrawableArc.SetFromObject(pDrawableElement);
        pDrawableElement = dynamic_cast<CDrawableElement*>(pConcept);
        oDrawableArc.SetToObject(pDrawableElement);

        oDrawableArc.Draw();

    }



    return CG_S_OK;
}

std::vector<CDrawableElement*> CDrawableSOA::ObjectsAt(int nXCoor, int nYCoor)
{
    CConcept::ConceptVector::iterator iterConcepts;
    CRelation::RelationVector::iterator iterRelations;
    CDrawableElement* pDrawableElement;
    std::vector<CDrawableElement*> vHitList;
    int nRC;

    for(iterConcepts = m_vectorConcept.begin();iterConcepts != m_vectorConcept.end();iterConcepts++)
    {
		pDrawableElement = dynamic_cast<CDrawableElement*>(*iterConcepts);
        if(pDrawableElement)
        {
            nRC = pDrawableElement->HitTest(nXCoor, nYCoor);
            if(nRC == CDrawableElement::RC_S_HitSucess)
            {
                vHitList.push_back(pDrawableElement);
            }
        }
        else
        {
            ASSERT(0);
        }
    }

    for(iterRelations = m_vectorRelation.begin();iterRelations != m_vectorRelation.end();iterRelations++)
    {
		pDrawableElement = dynamic_cast<CDrawableElement*>(*iterRelations);
        if(pDrawableElement)
        {
            nRC = pDrawableElement->HitTest(nXCoor, nYCoor);
            if(nRC == CDrawableElement::RC_S_HitSucess)
            {
                vHitList.push_back(pDrawableElement);
            }
        }
        else
        {
            ASSERT(0);
        }
    }
	return vHitList;

}
