/*******************************************************************************
*                                                                              *
* Société de Transports de Montréal.                                    	   *
* 2013                                                                         *
*                                                                              *
* Projet Zones Tests                                                           *
*                                                                              *
*                                                                              *
*                                                                              *
*******************************************************************************/
/*
    Description:
	Classe d'affichage d'un graphique discret (sondes magnétiques, pédales, etc.)La
	fonction SetData permet d'associer la liste des transitions.  La
	fonction DisplayData() permet de fixer le timespan à afficher.  La fonction détermine
	quels points sont dans le span et crée une liste de lignes qui sont ensuite affichés
	dans la fonction de rappel paint().

	Utilisée dans la page de visualisation des passages de train.

*/

/* ************************************************************************** */
/* Revision:
### 20131024 JFM
    Verision d'origine.

### YYYYMMDD Description du besoin ou du bug
    Description du changement.
 */

/* ************************************************************************** */

#include "GraphItem.h"
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QStyleOptionGraphicsItem>

CGraphItem::CGraphItem(QGraphicsItem *Parent)
{
	setParentItem(Parent);
	mDataSet = 0;
	mStartTime = mStopTime = 0;
	mDataValid = false;
    mLabel = new QGraphicsTextItem(this);
	mGraphPixmap = new QPixmap(boundingRect().width(),boundingRect().height());
}

CGraphItem::~CGraphItem()
{
	delete mGraphPixmap;
}

void CGraphItem::SetData(QList<CGraphDiscreteDataPair*> *DataList)
{

    mDataSet = DataList;
	//Build the lines list
}

unsigned int CGraphItem::DisplayData(quint64 StartTime, quint64 StopTime)
{
    if(mDataSet == 0)
        return RET_OK;

    quint64 MinTime = mDataSet->first()->mTime;
    quint64 MaxTime = mDataSet->last()->mTime;

    if(StartTime >= StopTime)
        return RET_ERROR;
    if(StartTime < MinTime)
       return RET_ERROR;
    if(StopTime > MaxTime)
       return RET_ERROR;

    mStartTime = StartTime;
    mStopTime = StopTime;
    quint64 TimeSpan = StopTime - StartTime;

    //Find the index of the first and last point in the timespan.
	int StartIndex = 0, StopIndex = 0;
    //quint64 StartDeltaTime, StopDeltaTime;
    int i = 0;
    bool StartFound = false, StopFound = false;
    while(StartFound == false || StopFound == false)
    {
        if(i >= mDataSet->size())
        {
            qDebug("GraphItem::Array overflow while searching for time index");
            return RET_ERROR;
        }

        quint64 CurTime = mDataSet->at(i)->mTime;
        if(CurTime <= StartTime)
        {
            StartIndex = i;
 //           StartDeltaTime = CurTime - StartTime;
            StartFound = true;
        }
        if(CurTime >= StopTime && !StopFound)
        {
            StopIndex = i;
//            StopDeltaTime = StopTime - mDataSet->at(StopIndex)->mTime;
            StopFound = true;
        }

        i++;
    }


    //Build the lines list
    mLinesList.clear();
    qreal Width = boundingRect().width();
	qreal Height = boundingRect().height()-2;
    qreal tick = (Width)/TimeSpan;	//pixels per microsec

    qreal X1,X2,Y1,Y2;

	//Add all the lines to create the graph.  When there is a transition
	//the horizontal line must be continued to the next point and a vertical
	//line must be drawn.
    for(int i = StartIndex; i < StopIndex; i++)
    {
        QLine NewLine;
        if(mDataSet->at(i)->mTime < StartTime)
            X1 = 0;
        else
            X1 = (qreal)(mDataSet->at(i)->mTime - StartTime);

        Y1 = mDataSet->at(i)->mValue;

        if(mDataSet->at(i+1)->mTime > StopTime)
        {
            X2 = StopTime - StartTime;
            Y2 = mDataSet->at(i)->mValue;   //Do not draw the vertical line if the point outside the span is not the same value.
        }
        else
        {
            X2 = mDataSet->at(i+1)->mTime - StartTime;
            Y2 = mDataSet->at(i+1)->mValue;
        }

        //Reverse the Y axis
        if(Y1 == 0)
            Y1 = 1;
        else
            Y1 = 0;
        if(Y2 == 0)
            Y2 = 1;
        else
            Y2 = 0;


        if(Y1 == Y2)	//no transition
        {
            NewLine.setLine(X1*tick,Y1*Height+1,X2*tick,Y2*Height+1);
            mLinesList.append(NewLine);
        }
        else	//value transition...
        {
            NewLine.setLine(X1*tick,Y1*Height+1,X2*tick,Y1*Height+1);	//horizontal line
            mLinesList.append(NewLine);
            NewLine.setLine(X2*tick,Y1*Height+1,X2*tick,Y2*Height+1);	//vertical line
            mLinesList.append(NewLine);
        }
    }

    mDataValid = true;

//#ifndef WINDOWS_OS
    mGraphPixmap->fill(QColor(245, 245, 255));
    QPainter *painter = new QPainter(mGraphPixmap);
    painter->drawLines(mLinesList);
    delete painter;
//#endif

	update();

	return RET_OK;
}

void CGraphItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	Q_UNUSED(option)
	Q_UNUSED(widget)

//			static int toto = 0;
//			qDebug("CGraphItem::paint %d",toto++);

	if(mDataValid == false)
		return ;
	if(mDataSet == 0)
		return;
	if(mDataSet->size() == 0)
		return;

//	painter->setClipRect(option->exposedRect);

//	QPen pen;
//	pen.setWidth(1);

//	pen.setColor(Qt::red);
//	painter->setPen(pen);
//	painter->drawRect(boundingRect());

//	pen.setColor(Qt::black);
//	painter->setPen(pen);

//#ifdef WINDOWS_OS
//    painter->drawLines(mLinesList);
//#else
    painter->drawPixmap(0,0,*mGraphPixmap);
//#endif
//	for(int i = 0; i < mLinesList.size(); i++)
//	{
//		painter->drawEllipse(mLinesList.at(i).p1(),2,2);
//	}

}

void CGraphItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
	event->ignore();
}


void CGraphItem::mouseReleaseEvent( QGraphicsSceneMouseEvent * event)
{
	event->ignore();
}

void CGraphItem::resizeEvent(QGraphicsSceneResizeEvent *event)
{
	Q_UNUSED(event)
	//mBackgroundRect->setRect(boundingRect());
	delete mGraphPixmap;
	mGraphPixmap = new QPixmap(boundingRect().width(),boundingRect().height());
	DisplayData(mStartTime,mStopTime);
}
void CGraphItem::SetLabel(QString label,int Offset)
{
    QFont font;
    font.setBold(true);
    mLabel->setFont(font);
    mLabel->setPlainText(label);
    mLabel->setPos(-Offset,boundingRect().height()/2 - mLabel->boundingRect().height()/2);
}


CGraphDiscreteDataPair::CGraphDiscreteDataPair(quint32 Value, quint64 Time):
    mValue(Value),
    mTime(Time)
{
}
