/***************************************************************************
 *   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 "previewwavedisplay.h"

PreviewWaveDisplay::PreviewWaveDisplay(QWidget *parent, const char *name)
    : QFrame(parent, name,WRepaintNoErase )
{
    soundfile=0;
    maxLengthDisplayedC=100000000;
    waveLength=0;
    displayedLength=0;
    leftBgColor.setRgb(255,220,220);
    rightBgColor.setRgb(220,220,255);
    fgColor.setRgb(0,0,200);
    buff=0;
    startDisplayPosition=0;
    jump=1;
    playingPosition=0;
    pixmap=0;
    redraw=TRUE;
    oldPositionLineX=0;
    moving=FALSE;
    fileScrewed=FALSE;
    
}


PreviewWaveDisplay::~PreviewWaveDisplay()
{
    if (buff) zaparr(buff);
    if (pixmap) zap(pixmap);
}

void PreviewWaveDisplay::drawContents ( QPainter * p){
    if(fileScrewed){
        if(!pixmap) 
                pixmap=new QPixmap(contentsRect().size().width()+5,contentsRect().size().height());
        QPainter painter(pixmap);
        painter.fillRect(contentsRect(),QBrush(QColor(255,100,100)));
        painter.drawText(contentsRect(),Qt::AlignCenter,"This file seems broken");
        p->drawPixmap(0,0,*pixmap);
        painter.end();
        return;
    }
    if(!pixmap) redraw=TRUE;
    if(buff){
        if(redraw){
            if(!pixmap) 
                pixmap=new QPixmap(contentsRect().size().width()+5,contentsRect().size().height());
            QPainter painter(pixmap);
            painter.drawLine(0,height()/4,contentsRect().width(),height()/4);
            painter.drawLine(0,3*height()/4,contentsRect().width(),3*height()/4);
            int x=0;
            float heightFactor=0.95*(height()/4);
            painter.fillRect(contentsRect().x(),contentsRect().y(),
                        contentsRect().width(),contentsRect().height()/2,QBrush(leftBgColor));
            painter.fillRect(contentsRect().x(),contentsRect().y()+contentsRect().height()/2,
                        contentsRect().width(),contentsRect().height()/2,QBrush(rightBgColor));
            for (int i=startDisplayPosition;i<startDisplayPosition+displayedLength-jump;i+=jump){
                int translate=height()/4;
                float maxL=0;
                float maxR=0;
                float minL=0;
                float minR=0;
                int count=i;
                for (int j=i;j<i+jump;j++){
                    float valL=buff[count];
                    float valR=buff[count+1];
                    if(valL>=0){
                        if(valL>maxL) maxL=valL;
                    }else if(valL<=0){
                        if(valL<minL) minL=valL;
                    }
                    if(valR>=0){
                        if(valR>maxR) maxR=valR;
                    }else if(valR<=0){
                        if(valR<minR) minR=valR;
                    }
                    count++;
                }
                int color=int(128-(fabs(maxL)>fabs(minL)?fabs(maxL):fabs(minL))*128.0);
                fgColor.setRgb(color,color,255);
                painter.setPen(fgColor);
                painter.drawLine(x,translate,x,int(translate-heightFactor*minL));
                painter.drawLine(x,translate,x,int(translate-heightFactor*maxL));
                color=int(128-(fabs(maxR)>fabs(minR)?fabs(maxR):fabs(minR))*128.0);
                fgColor.setRgb(255,color,color);
                painter.setPen(fgColor);
                painter.drawLine(x,translate*3,x,int(translate*3-heightFactor*minR));
                painter.drawLine(x,translate*3,x,int(translate*3-heightFactor*maxR));
                x++;
            }
            painter.end();
        }
        int positionLineX=(playingPosition-startDisplayPosition)/jump;
        //int repaint_width=int(fabs(positionLineX-oldPositionLineX)+5);
        oldPositionLineX=positionLineX;
        //if(redraw){
            p->drawPixmap(0,0,*pixmap);
        //}else{
          //  p->drawPixmap(positionLineX-repaint_width,0,
            //              *pixmap,positionLineX-repaint_width,0,repaint_width*2,contentsRect().height());
        //}
        p->setPen(QColor(255,0,0));
            p->drawLine(positionLineX,0,positionLineX,contentsRect().height()-1);
            p->drawPixmap(positionLineX-5,contentsRect().height()/2-3,
                                        QPixmap(qembed_findImage("player_play-small")));
                redraw=FALSE;

    }
}




/*!
    \fn PreviewWaveDisplay::setSoundFile(QString)
 */
void PreviewWaveDisplay::setSoundFile(QString* file)
{
    soundfile=file;
    if(soundfile) loadWave();
}


/*!
    \fn PreviewWaveDisplay::setDisplayedLength(long mdl)
 */
void PreviewWaveDisplay::setDisplayedLength(int mdl)
{
    displayedLength=mdl;
    jump=displayedLength/contentsRect().width();
    jump=jump<1?1:jump;
    int maxStartPosition=waveLength-displayedLength;
    emit(maxStartPositionChangedSig(maxStartPosition));
    redraw=TRUE;
    update();
}


/*!
    \fn PreviewWaveDisplay::getDisplayedLength()
 */
int PreviewWaveDisplay::getDisplayedLength()
{
    return displayedLength;
}


/*!
    \fn PreviewWaveDisplay::loadWave()
 */
void PreviewWaveDisplay::loadWave()
{
    if(soundfile){
        SF_INFO sfinfo;
        SNDFILE* tmp_sndfile= sf_open(soundfile->ascii(), SFM_READ, &sfinfo);
        if (!tmp_sndfile){
            fileScrewed=TRUE;
            sf_close(tmp_sndfile);
            return;
        }else{
            fileScrewed=FALSE;
        }
        waveLength=sfinfo.frames<maxLengthDisplayedC?sfinfo.frames:maxLengthDisplayedC;
        if(buff) zaparr(buff);
        buff=new float[waveLength*2];
        sf_readf_float(tmp_sndfile, buff,(sf_count_t)waveLength);
        sf_close(tmp_sndfile);
        startDisplayPosition=0;
        playingPosition=0;
        jump=waveLength/contentsRect().width();
        jump=jump<1?1:jump;
        displayedLength=waveLength;
        redraw=TRUE;
    }
}


/*!
    \fn PreviewWaveDisplay::getWaveLength()
 */
int PreviewWaveDisplay::getWaveLength()
{
    return waveLength;
}


/*!
    \fn PreviewWaveDisplay::setStartDisplayposition(int sdp)
 */
void PreviewWaveDisplay::setStartDisplayPosition(int sdp)
{
    startDisplayPosition=sdp<0?0:sdp;
    redraw=TRUE;
    update();
}


/*!
    \fn PreviewWaveDisplay::getJump()
 */
int PreviewWaveDisplay::getJump()
{
    return jump;
}

void PreviewWaveDisplay::customEvent(QCustomEvent* ev)
{
    if(ev->type() == PLAY_POSITION_CHANGED_EVENT){
        playingPosition=(((PlayPositionChanged*)ev)->getPosition());
        if(playingPosition<waveLength){
            bool playing=(((PlayPositionChanged*)ev)->getPlaying());
            if(playingPosition<startDisplayPosition ||
               (playingPosition>startDisplayPosition+displayedLength && startDisplayPosition<=waveLength-displayedLength)){
                emit(startPositionChangedSig(playingPosition));
                startDisplayPosition=playingPosition;
            }

            if(!playing){
                //startDisplayPosition=playingPosition;
                //emit(startPositionChangedSig(playingPosition));
                emit(stopSig());
            }
            //redraw=FALSE;
            update();
        }
    }
}

void PreviewWaveDisplay::paintEvent ( QPaintEvent * event ){
    QFrame::paintEvent(event);
}

/*!
    \fn PreviewWaveDisplay::sizeHint()
 */
QSize PreviewWaveDisplay::minimumSizeHint() const
{
    return QSize(200,120);
}

void PreviewWaveDisplay::resizeEvent ( QResizeEvent * /*ev*/){
    jump=displayedLength/contentsRect().width();
    if(pixmap) zap(pixmap);
    redraw=TRUE;
}

void PreviewWaveDisplay::mousePressEvent ( QMouseEvent * e ){
    int positionLineX=(playingPosition-startDisplayPosition)/jump;
    if (e->pos().x()>positionLineX-5 && e->pos().x()<positionLineX+5 &&
        e->pos().y()>contentsRect().height()/2-3 && e->pos().y()<contentsRect().height()/2+3){
        moving=TRUE;
        emit(pauseSig());
    }
}

void PreviewWaveDisplay::mouseMoveEvent ( QMouseEvent * e ){
    if(moving){
        playingPosition=(e->pos().x()*jump)+startDisplayPosition;
        playingPosition=playingPosition<0?0:playingPosition;
        playingPosition=playingPosition>waveLength-1?
                                        waveLength-1:playingPosition;
        emit(playPositionChangedSig(playingPosition));
        update();
    }
}

void PreviewWaveDisplay::mouseReleaseEvent ( QMouseEvent * /*e*/ ){
    if(moving){
        moving=FALSE;
        emit(playSig());
    }
}

long PreviewWaveDisplay::getPlayingPosition() const {
    return playingPosition;
}
