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

LockedBeatRect::LockedBeatRect(QCanvas* canvas,BeatLine* start,BeatLine* end,SoundManager* sm)
 : QCanvasRectangle(canvas), Blinkable()
{
    drawRedRect=FALSE;
    soundManager=sm;
    startBL=start;
    endBL=end;
    bgColor.setRgb(255,255,200);
    if(startBL && endBL){
        setX(startBL->x());
        setSize(int(endBL->x()-startBL->x()),canvas->height()-20);
        setY(20);
        handle=new QRect(int(x()+width()/2-4),(height()/2)+20-4,8,8);
        pitchshiftHandle=new QRect(int(x()+width()/2-8),(height()/2)+20-8,17,17);
    }
    selected=FALSE;
    sampleNumberDisplays.setAutoDelete(TRUE);
    updateSampleDisplays();
}


LockedBeatRect::~LockedBeatRect()
{
    sampleNumberDisplays.clear();
}

int LockedBeatRect::rtti() const{
    return RTTI_LOCKEDBEATRECT;
}

void LockedBeatRect::drawShape ( QPainter & p ){
    if(startBL && endBL){
        setX(startBL->x());
        int middle=(canvas()->height()/2)+20;
        setSize(int(endBL->x()-startBL->x()),canvas()->height()-20);
        setY(20);
        handle->setRect(int(x()+width()/2-4),middle-4,8,8);

        //pitchshiftHandle->setRect(x()+width()/2-8,middle-20-8,17,17);
        pitchshiftHandle->setRect(0,0,0,0);

        QPointArray triangle1(3);
        triangle1.setPoint(0,QPoint(int(x()),middle));
        triangle1.setPoint(1,QPoint(int(x())+5,middle+2));
        triangle1.setPoint(2,QPoint(int(x())+5,middle-2));

        QPointArray triangle2(3);
        triangle2.setPoint(0,QPoint(int(x())+width(),middle));
        triangle2.setPoint(1,QPoint(int(x())+width()-5,middle+2));
        triangle2.setPoint(2,QPoint(int(x())+width()-5,middle-2));


        RasterOp oldROP=p.rasterOp();
        p.setRasterOp(AndROP);
        if(drawRedRect){
            p.fillRect(rect(),QBrush(red));
        }else{
            if(isSelected()){
                p.setPen(QPen(red,2));
                p.setBrush(QBrush(red));
                p.fillRect(rect(),QBrush(QColor(255,200,200)));
            }else{
                p.setPen(QPen(magenta,2));
                p.setBrush(QBrush(magenta));
                p.fillRect(rect(),QBrush(bgColor));
            }
            p.drawPolygon(triangle1);
            p.drawPolygon(triangle2);
            p.drawLine(int(startBL->x()),middle,int(endBL->x()),middle);
            p.drawPixmap(*handle,QPixmap(qembed_findImage("leftrightarrow-small")));
             p.drawPixmap(*pitchshiftHandle,QPixmap(qembed_findImage("pitchshift")));
        }
        p.setRasterOp(oldROP);        
    }else{
        cout<<"start and end bl missing!!\n";
    }
    
}

QPointArray  LockedBeatRect::areaPoints() const{
    return QCanvasRectangle::areaPoints();
}


/*!
    \fn LockedBeatRect::setColor(int i)
 */
void LockedBeatRect::setColor(int i)
{
    if(i%2==0) bgColor.setRgb(255,255,220);
    else bgColor.setRgb(220,255,255);
}


/*!
    \fn LockedBeatRect::getHandle()
 */
QRect* LockedBeatRect::getHandle()
{
    return handle;
}


/*!
    \fn LockedBeatRect::setSelected(bool tf)
 */
void LockedBeatRect::setSelected(bool tf)
{
    selected=tf;
    update();
}


/*!
    \fn LockedBeatRect::isSelected()
 */
bool LockedBeatRect::isSelected()
{
    return selected;
}


/*!
    \fn LockedBeatRect::getStartSample()
 */
long LockedBeatRect::getStartSample()
{
    if(startBL) return startBL->getBeatPos();
    else return -1;
}


/*!
    \fn LockedBeatRect::getEndSample()
 */
long LockedBeatRect::getEndSample()
{
    if(endBL) return endBL->getBeatPos();
    else return -1;
}


/*!
    \fn LockedBeatRect::getNb()
 */
int LockedBeatRect::getNb()
{
    return number;
}


/*!
    \fn LockedBeatRect::setNb(int n)
 */
void LockedBeatRect::setNb(int n)
{
    number=n;
}

bool LockedBeatRect::operator<(LockedBeatRect brect)
{
    cout<<"comparing <\n";
    return getStartSample()<brect.getStartSample();
}

bool LockedBeatRect::operator==(LockedBeatRect brect)
{
    cout<<"comparing ==\n";
    return (getStartSample()==brect.getStartSample() &&
            getEndSample()==brect.getEndSample());
}

/*!
    \fn LockedBeatRect::updateGeom()
 */
void LockedBeatRect::updateGeom()
{
    if(startBL && endBL){
        setX(startBL->x());
        setSize(int(endBL->x()-startBL->x()),canvas()->height()-20);
        setY(20);
        handle=new QRect(int(x()+width()/2-4),(height()/2)+20-4,8,8);
        updateSampleDisplays();
    }
}


/*!
    \fn LockedBeatRect::addSampleNumberDisplay(SampleNumberDisplay* snd)
 */
void LockedBeatRect::addSampleNumberDisplay(SampleNumberDisplay* snd)
{
    cout<<"SampleNumberDisplay added\n";
    snd->setNumber(sampleNumberDisplays.count());
    snd->show();
    copySceneStatus(snd);
    sampleNumberDisplays.append(snd);
    updateSampleDisplays();
}


/*!
    \fn LockedBeatRect::removeSampleNumberDisplay(SampleNumberDisplay* snd)
 */
void LockedBeatRect::removeSampleNumberDisplay(SampleNumberDisplay* snd)
{
    sampleNumberDisplays.remove(snd);
}


/*!
    \fn LockedBeatRect::updateSampleDisplays()
 */
void LockedBeatRect::updateSampleDisplays()
{
    QPtrListIterator<SampleNumberDisplay> it( sampleNumberDisplays );
    SampleNumberDisplay *snd;
    while ( (snd = it.current()) != 0 ) {
        ++it;
        int new_snd_width=int(endBL->x()-startBL->x()>=35?30:
            endBL->x()-startBL->x()-5);
        snd->setSize(new_snd_width,snd->height());
        snd->setX(x()+width()-snd->width());
        snd->setY(height()-30-(snd->getNumber()*(snd->height())-2));
        if(snd->getNumber()==0 && sampleNumberDisplays.count()>1) snd->setCanErase(FALSE);
        else snd->setCanErase(TRUE);
        //cout<<"br["<<getNb()<<"] updated: "<<snd->getNumber()<<endl;;
    }
    update();
}


/*!
    \fn LockedBeatRect::getSampleNumberDisplaysRect()
 */
QRect LockedBeatRect::getSampleNumberDisplaysRect()
{
    QRect resultRect(0,0,0,0);
    QPtrListIterator<SampleNumberDisplay> it( sampleNumberDisplays );
    SampleNumberDisplay *snd;
    while ( (snd = it.current()) != 0 ) {
        ++it;
        resultRect=resultRect.unite(snd->rect());
    }
    return resultRect;
}


/*!
    \fn LockedBeatRect::mousePressEvent(QMouseEvent* ev)
 */
void LockedBeatRect::mousePressEvent(QMouseEvent* ev)
{
    QPtrListIterator<SampleNumberDisplay> it( sampleNumberDisplays );
    SampleNumberDisplay *snd;
    while ( (snd = it.current()) != 0 ) {
       if(snd->rect().contains(ev->pos())){
        if(snd->getEraseHandle()->contains(ev->pos())){
            if(snd->getCurrent()){
                if(it.atFirst() && sampleNumberDisplays.count()>1){
                    setCurrentSND(++it);
                }else{
                    setCurrentSND(--it);
                }
                if (sampleNumberDisplays.count()>1){
                    soundManager->replaceFileAt(it.current()->getAssignedFile(),
                                                startBL->getBeatPos(), endBL->getBeatPos());
                }
            }
            setSceneStatus(snd->getScene(),FALSE);
            removeSampleNumberDisplay(snd);
            renumberSampleNumberDisplays();
            updateSampleDisplays();
            return;
        }else if(snd->getSceneHandle()->contains(ev->pos())){
            int oldScene=snd->getScene();
            snd->incrementScene();
            setSceneStatus(snd->getScene(),TRUE);
            if(snd->getScene()!=oldScene)setSceneStatus(oldScene,FALSE);
            updateSampleDisplays();
            return;
        }else{
            if(!snd->getCurrent()){
                setCurrentSND(snd);
                soundManager->replaceFileAt(snd->getAssignedFile(),
                                                    startBL->getBeatPos(), endBL->getBeatPos());
                updateSampleDisplays();
            }
            return;
        }
       }
       ++it;
    }
}


/*!
    \fn LockedBeatRect::setCurrentSND(SampleNumberDisplay* snd)
 */
void LockedBeatRect::setCurrentSND(SampleNumberDisplay* snd)
{
        QPtrListIterator<SampleNumberDisplay> it( sampleNumberDisplays );
        SampleNumberDisplay *snd2;
        while ( (snd2 = it.current()) != 0 ) {
            ++it;
            if(snd2==snd){
                snd2->setCurrent(TRUE);
            }
            else snd2->setCurrent(FALSE);
        }
}


/*!
    \fn LockedBeatRect::getSNDCount()
 */
int LockedBeatRect::getSNDCount()
{
    return sampleNumberDisplays.count();
}


/*!
    \fn LockedBeatRect::renumberSampleNumberDisplays()
 */
void LockedBeatRect::renumberSampleNumberDisplays()
{
    QPtrListIterator<SampleNumberDisplay> it( sampleNumberDisplays );
    sampleNumberDisplays.sort();
    SampleNumberDisplay *snd;
    int count=0;
    while ( (snd = it.current()) != 0 ) {
        ++it;
        snd->setNumber(count++);
    }
}


/*!
    \fn LockedBeatRect::setSceneStatus(int sn, bool status)
 */
void LockedBeatRect::setSceneStatus(int sn, bool status)
{
    QPtrListIterator<SampleNumberDisplay> it( sampleNumberDisplays );
    SampleNumberDisplay *snd;
    while ( (snd = it.current()) != 0 ) {
        ++it;
        snd->setSceneStatus(sn,status);
    }
}


/*!
    \fn LockedBeatRect::copySceneStatus(SampleNumberDisplay* snd)
 */
void LockedBeatRect::copySceneStatus(SampleNumberDisplay* snd)
{
    if(sampleNumberDisplays.count()>0){
        for (int i=0;i<snd->getSceneCount();i++){
            snd->setSceneStatus(i,(*sampleNumberDisplays.at(0)).getSceneStatus(i));
        }
    }
}


/*!
    \fn LockedBeatRect::switchScene(int sc)
 */
void LockedBeatRect::switchScene(int sc)
{
    QPtrListIterator<SampleNumberDisplay> it( sampleNumberDisplays );
    SampleNumberDisplay *snd;
    while ( (snd = it.current()) != 0 ) {
        ++it;
        if(snd->getScene()==sc){
                setCurrentSND(snd);
                updateSampleDisplays();
                soundManager->replaceFileAt(snd->getAssignedFile(),
                                                    startBL->getBeatPos(), endBL->getBeatPos());
                return;
            }
    }
}


/*!
    \fn LockedBeatRect::assignSceneToCurrent(int sc)
 */
void LockedBeatRect::assignSceneToCurrent(int sc)
{
    QPtrListIterator<SampleNumberDisplay> it( sampleNumberDisplays );
    SampleNumberDisplay *snd;
    while ( (snd = it.current()) != 0 ) {
        ++it;
        if(snd->getScene()==sc && !snd->getCurrent()){
            snd->setScene(0);
        }
        if(snd->getCurrent()){
            setSceneStatus(snd->getScene(),FALSE);
            snd->setScene(sc);
            
        }
    }
    setSceneStatus(sc,TRUE);
    canvas()->update();
}


/*!
    \fn LockedBeatRect::getSampleNumberDisplays()
 */
QPtrList <SampleNumberDisplay> LockedBeatRect::getSampleNumberDisplays()
{
    return sampleNumberDisplays;
}


/*!
    \fn LockedBeatRect::updateSceneStatus()
 */
void LockedBeatRect::updateSceneStatus()
{
    bool* scenestatus =new bool(7);
    for (int i=0;i<7;i++){
        scenestatus[i]=FALSE;
    }
    if(sampleNumberDisplays.count()>0){
        for (uint i=0;i<sampleNumberDisplays.count();i++){
            scenestatus[sampleNumberDisplays.at(i)->getScene()]=TRUE;
        }
        for (uint i=0;i<sampleNumberDisplays.count();i++){
            sampleNumberDisplays.at(i)->setSceneStatus(scenestatus);
        }
    }
    zaparr(scenestatus);
}


/*!
    \fn LockedBeatRect::canRemove()
 */
bool LockedBeatRect::canRemove()
{
    return (getSNDCount()==0);
}


/*!
    \fn LockedBeatRect::blink(int step)
 */
void LockedBeatRect::executeBlink(int step)
{
    if(step==1) drawRedRect=TRUE;
    else drawRedRect=FALSE;
    canvas()->setChanged(rect());
    canvas()->update();
}


BeatLine* LockedBeatRect::getStartBL(){
    return startBL;
}


BeatLine* LockedBeatRect::getEndBL(){
    return endBL;
}


/*!
    \fn LockedBeatRect::getPitchshiftHandle()
 */
QRect* LockedBeatRect::getPitchshiftHandle()
{
    return pitchshiftHandle;
}
