/***************************************************************************
 *   Copyright (C) 2004 by Predrag Viceic                                  *
 *   viceic@net2000.ch                                            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "polyline.h"

PolyLine::PolyLine(QCanvas* canvas)
 : QCanvasPolygon(canvas)
{
    setY(0);
    setZ(10);
    canvasSize.setWidth(1);
    canvasSize.setHeight(1);
}


PolyLine::~PolyLine()
{
}

/*!
    \fn PolyLine::rtti()
 */
int PolyLine::rtti() const
{
    return RTTI_POLYLINE;
}

void PolyLine::drawShape ( QPainter & p ){
    QPen pen=p.pen();
    p.setPen(QPen(darkBlue,1));
    qHeapSort(points);
    for (int i=0;i<points.count();i++){
        if(points[i]!=points.last()){
            if(points[i].selected() || points[i+1].selected()){
                p.setPen(QPen(red,1));
            }else{
                p.setPen(QPen(darkBlue,1));
            }
            p.drawLine(points[i].x(),points[i].y(),points[i+1].x(),points[i+1].y());
        }
        p.setPen(QPen(darkBlue,1));
        if(points[i].selected()){
            p.fillRect(points[i].x()-3,points[i].y()-3,7,7,QBrush(red));
        }else{
            p.fillRect(points[i].x()-3,points[i].y()-3,7,7,QBrush(cyan));
        }
        p.drawRect(points[i].x()-3,points[i].y()-3,7,7);
    }
    p.setPen(pen);
}


QPointArray PolyLine::areaPoints () const{
    QPointArray result(4);
    result.setPoint(0,QPoint(points.first().x()-4,-1));
    result.setPoint(1,QPoint(points.last().x()+4,-1));
    result.setPoint(2,QPoint(points.last().x()+4,canvas()->height()+1));
    result.setPoint(3,QPoint(points.first().x()-4,canvas()->height()+1));
    return result;
}


/*!
    \fn PolyLine::addPoint(QPoint p,long sample_pos,float value)
 */
void PolyLine::addPoint(QPoint p,long sample_pos,float value)
{
    SortablePoint sp(p);
    sp.setSamplePos(sample_pos);
    sp.setValue(value);
    if (!points.contains(sp) && !containsSameX(p)){
        points.append(sp);
        deselectAll();
    }
    else{
       for (int i=0;i<points.count();i++){
           if(points[i]==sp){points[i].setSelected(TRUE);break;}
        }
    }
    qHeapSort(points);
    setPoints(toPointArray());
    update();
}

/*!
    \fn PolyLine::removePoint(QPoint p)
 */
void PolyLine::removePoint(QPoint p)
{
    SortablePoint sp(p);
    if (points.contains(sp)){
        if(points.first()==sp || points.last()==sp){
            canvas()->setAllChanged();
        }
        points.remove(sp);
    }
    qHeapSort(points);
    setPoints(toPointArray());
    deselectAll();
    canvas()->setAllChanged();
    update();
}

/*!
    \fn PolyLine::moveSelectedPoint(QPoint to, long sample_pos, float value)
 */
void PolyLine::moveSelectedPoint(QPoint to, long sample_pos, float value)
{
    for (int i=0;i<points.count();i++){
        if(points[i].selected()){
            if(points.first()==points[i] || points.last()==points[i]){
                canvas()->setAllChanged();
            }
            if((points.contains(SortablePoint(to))<=1) && !containsSameX(to)){
                points[i].setX(to.x());
                points[i].setY(to.y());
                points[i].setSamplePos(sample_pos);
                points[i].setValue(value);
                break;
            }
        }
    }
    qHeapSort(points);
    setPoints(toPointArray());
    update();
}


/*!
    \fn PolyLine::deselectAll()
 */
void PolyLine::deselectAll()
{
    for (int i=0;i<points.count();i++){
        points[i].setSelected(FALSE);
    }
    update();
}

/*!
    \fn PolyLine::getYAtX(int)
 */
int PolyLine::getYAtX(int x)
{
    for (int i=1;i<points.count();i++){
        if(points[i].x()>x){
            int x1=points[i-1].x();
            int y1=points[i-1].y();
            int x2=points[i].x();
            int y2=points[i].y();
            float a=float((y2-y1))/float((x2-x1));
            float b=y1-(a*float(x1));
            return a*x+b;
        }
    }
    return -1;
}

/*!
    \fn PolyLine::getValueAtSample(long sample)
 */
float PolyLine::getValueAtSample(long sample)
{
    for (int i=1;i<points.count();i++){
        if(points[i].getSamplePos()>sample){
            long x1=points[i-1].getSamplePos();
            float y1=points[i-1].getValue();
            long x2=points[i].getSamplePos();
            float y2=points[i].getValue();
            float a=float((y2-y1))/float((x2-x1));
            float b=y1-(a*float(x1));
            return a*float(sample)+b;
        }
    }
    return -1;
}

QRect PolyLine::boundingRect(){
    return QRect(QPoint(points.first().x(),0),
                 QPoint(points.last().x(),canvas()->height()));
}

/*!
    \fn PolyLine::count()
 */
int PolyLine::count()
{
    return points.count();
}


/*!
    \fn PolyLine::clear()
 */
void PolyLine::clear()
{
    points.clear();
    setPoints(toPointArray());
    canvas()->setAllChanged();
    update();
}


/*!
    \fn PolyLine::updateSize(QSize size)
 */
void PolyLine::updateSize(QSize size)
{
    if(canvasSize.isValid() && size.isValid()){
        QWMatrix matrix;
        matrix.setTransformationMode(QWMatrix::Points);
        matrix.scale(float(size.width())/float(canvasSize.width()),
                     float(size.height())/float(canvasSize.height()));
        for(int i=0;i<points.count();i++){
            long sample_pos=points[i].getSamplePos();
            float value=points[i].getValue();
            points[i]=SortablePoint(matrix.map(points[i]));
            points[i].setSamplePos(sample_pos);
            points[i].setValue(value);
        }
        qHeapSort(points);
        setPoints(toPointArray());
    }
    if(size.isValid()){
        canvasSize.setWidth(size.width());
        canvasSize.setHeight(size.height());
    }
    canvas()->setAllChanged();
    update();
}


/*!
    \fn PolyLine::containsSameX(QPoint p)
 */
int PolyLine::containsSameX(QPoint p)
{
    int count=0;
    for (int i=0;i<points.count();i++){
        if (points[i].x()==p.x()) count++;
    }
    return count;
}


/*!
    \fn PolyLine::toPointArray()
 */
QPointArray PolyLine::toPointArray()
{
    QPointArray array(points.count());
    for (int i=0;i<points.count();i++){
        array.setPoint(i,QPoint(points[i].x(),points[i].y()));
    }
    return array;
}
