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

EffectFrame::EffectFrame(LADSPAEffect* _eff, QWidget* parent,const char* name)
 : QVBox(parent,name)
{
    setBackgroundColor(red);
    effect=_eff;
    if (!effect->wasPortInitDone()) effect->initControlPortsValues();
    effect->setPortInitDone(TRUE);

    portsBar=new QMenuBar(this);
    QPopupMenu * portsMenu = new QPopupMenu( this );
    executeMenu = new QPopupMenu( this );

    QFont t_font=portsBar->font();
    t_font.setPointSize(8);
    t_font.setWeight(QFont::Light);
    portsMenu->setFont(t_font);
    t_font.setPointSize(9);
    t_font.setWeight(QFont::Bold);
    portsBar->setFont(t_font);
    stack=new QWidgetStack(this);

    portsBar->insertItem(effect->getName(),portsMenu);
    portsBar->insertItem("Execute",executeMenu);

    QHButtonGroup* drawModeBG=new QHButtonGroup(portsBar);
    drawModeBG->setExclusive(TRUE);
    drawModeBG->setInsideMargin(0);
    drawModeBG->setInsideSpacing(0);
    drawModeBG->setFrameShape(NoFrame);

    portsBar->insertItem(drawModeBG);

    pointsButton=new QPushButton(".",drawModeBG);
    pointsButton->setToggleButton(TRUE);
    pointsButton->setOn(TRUE);

    linesButton=new QPushButton("L",drawModeBG);
    linesButton->setToggleButton(TRUE);

    polylinesButton=new QPushButton("P",drawModeBG);
    polylinesButton->setToggleButton(TRUE);

    splinesButton=new QPushButton("S",drawModeBG);
    splinesButton->setToggleButton(TRUE);



    onReleasePolMenuIDX=executeMenu->insertItem("Apply effect on release",
                                                this,SLOT(switchOnReleaseApplyPolicy()),0,1);
    onChangePolMenuIDX=executeMenu->insertItem("Realtime (unstable)",this,SLOT(switchOnChangeApplyPolicy()),0,2);
    //executeMenu->setItemEnabled(2,FALSE);


    portsBar->show();
    //portFrames.setAutoDelete(TRUE);
    for (QPtrList<LADSPAPort>::Iterator it=effect->getControlInputPorts()->begin();
            it!=effect->getControlInputPorts()->end();++it){
            QString portName=(*it)->getPortName();
            portName.append(" (").append(QString::number((*it)->getLowerBound())).
                append(" - ").
                append(QString::number((*it)->getUpperBound())).append(")");
        if((*it)->areBoundsOk()){
            EffectPortFrame* tempFrame=new EffectPortFrame(portName.copy(),*it,stack);
            portFrames.append(tempFrame);
            portsMenu->insertItem(portName,tempFrame,SLOT(raiseMe()));
            stack->addWidget(tempFrame);
            tempFrame->show();
            tempFrame->setBackgroundColor(yellow);
            connect(tempFrame,SIGNAL(valueChanged(long,long)),
                              this,SLOT(apply(long,long)));
            connect(tempFrame,SIGNAL(drawModeChanged(EffectPortFrame::DrawMode)),
                    this,SLOT(changeDrawMode(EffectPortFrame::DrawMode)));
            connect(pointsButton,SIGNAL(pressed()),
                                tempFrame,SLOT(pointsToggled()));
            connect(linesButton,SIGNAL(pressed()),
                                tempFrame,SLOT(linesToggled()));
            connect(polylinesButton,SIGNAL(pressed()),
                                tempFrame,SLOT(polylinesToggled()));
            connect(splinesButton,SIGNAL(pressed()),
                    tempFrame,SLOT(splinesToggled()));
            connect(this,SIGNAL(beatLinesChangedS(QValueList< beatline_data > )),
                    tempFrame,SLOT(beatLinesChanged(QValueList< beatline_data > )));
            connect(this,SIGNAL(lockedBeatLinesChangedS(QValueList< beatline_data > )),
                    tempFrame,SLOT(lockedBeatLinesChanged(QValueList< beatline_data > )));
            connect(this,SIGNAL(zoomRatioChangedS(long )),
                    tempFrame,SLOT(setZoomRatio(long )));
            connect(this,SIGNAL(applyPolicyChanged(int )),
                    tempFrame,SLOT(setApplyPolicy(int )));
            connect(this,SIGNAL(cropS(long,long)),tempFrame,SLOT(crop(long, long )));
        }else{
            int id=portsMenu->insertItem(portName);
            portsMenu->setItemEnabled(id,FALSE);
        }
    }
    update();
    //adjustSize();
    if(portFrames.count()>0) portFrames.first()->raiseMe();
    switchOnReleaseApplyPolicy();
}

EffectFrame::~EffectFrame()
{
  /*  
    delete pointsButton;
    delete linesButton;
    delete polylinesButton;
    delete splinesButton;
    delete drawModeBG;
    delete portsBar;
    delete executeMenu;
*/
}

void EffectFrame::apply(){
    emit(applyMe(effect));
}


void EffectFrame::apply(long start_sample,long end_sample){
    emit(applyMe(effect,start_sample,end_sample));
}

void EffectFrame::show(){
    QVBox::show();
    if(portFrames.count()>0) portFrames.first()->raiseMe();
}

void EffectFrame::closeEvent( QCloseEvent* ce ){

     for (QPtrList<EffectPortFrame>::Iterator it=portFrames.begin();
            it!=portFrames.end();++it){
                stack->removeWidget(*it);
                (*it)->close(TRUE); //close and delete the frame
    }
    portFrames.clear(); //delete the pointers to frames
    ce->accept();
}





/*!
    \fn EffectFrame::setZoomRatio(long)
 */
void EffectFrame::setZoomRatio(long _zr)
{
    emit(zoomRatioChangedS(_zr));
}

void EffectFrame::visibleAreaChanged(long /*start_sample*/, long /*end_sample*/){
    //view->setStartSamplePosition(start_sample);
    //view->setEndSamplePosition(end_sample);
    //updateViewWindow();
}


/*!
    \fn EffectFrame::setContentsPos/int,int)
 */
void EffectFrame::setContentsPos(int x,int /*y*/)
{
    //cout<<"EffectFrame::setContentsPos(int "<<x<<",int "<<y<<")\n";
    for (QPtrList<EffectPortFrame>::Iterator it=portFrames.begin();
            it!=portFrames.end();++it){
                (*it)->setContentsPos(x,0);
                (*it)->update();
                //cout<<(*it)->getCanvas()->width()<<endl;
    }
}

void EffectFrame::switchOnReleaseApplyPolicy(){
    executeMenu->setItemChecked(onReleasePolMenuIDX,TRUE);
    executeMenu->setItemChecked(onChangePolMenuIDX,FALSE);
    setApplyPolicy(EffectPortFrame::APPLY_ON_RELEASE);
    //apply();
}
void EffectFrame::switchOnChangeApplyPolicy(){
    executeMenu->setItemChecked(onChangePolMenuIDX,TRUE);
    executeMenu->setItemChecked(onReleasePolMenuIDX,FALSE);
    setApplyPolicy(EffectPortFrame::APPLY_ON_CHANGE);
}




/*!
    \fn EffectFrame::setApplyPolicy(int)
 */
void EffectFrame::setApplyPolicy(int ap)
{
    emit(applyPolicyChanged(ap));
}


/*!
    \fn EffectFrame::setEffectNotApplied()
 */
void EffectFrame::reinit()
{

}


QSize EffectFrame::sizeHint () const {
    return QSize(parentWidget()->width(),100);
}







/*!
    \fn EffectFrame::changeDrawMode(DrawMode dm)
 */
void EffectFrame::changeDrawMode(EffectPortFrame::DrawMode dm)
{
    switch(dm){
        case EffectPortFrame::DRAW_MODE_POINTS:{pointsButton->setOn(TRUE);break;}
        case EffectPortFrame::DRAW_MODE_LINES:{linesButton->setOn(TRUE);break;}
        case EffectPortFrame::DRAW_MODE_POLYLINES:{polylinesButton->setOn(TRUE);break;}
        case EffectPortFrame::DRAW_MODE_SPLINES:{splinesButton->setOn(TRUE);break;}
    }
}

void EffectFrame::lockedBeatLinesChanged(QValueList <beatline_data> vl){
    emit(lockedBeatLinesChangedS(vl));
}
void EffectFrame::beatLinesChanged(QValueList <beatline_data> vl){
    emit(beatLinesChangedS(vl));
}





/*!
    \fn EffectFrame::getLadspa()
 */
LADSPAEffect* EffectFrame::getLadspa()
{
    return effect;
}




/*!
    \fn EffectFrame::getPortFrame(int portNo)
 */
EffectPortFrame* EffectFrame::getPortFrame(int portNo)
{
    for (QPtrList<EffectPortFrame>::Iterator it=portFrames.begin();
         it!=portFrames.end();++it){
             if((*it)->getPortNumber()==portNo) return (*it);
         }
    return NULL;
}


/*!
    \fn EffectFrame::setSplineData(int port_no, QValueList<SplinePoint>)
 */
void EffectFrame::setSplineData(int port_no, QValueList<SplinePoint> _spline)
{
    getPortFrame(port_no)->setSplineData(_spline);
}


/*!
    \fn EffectFrame::setPolylineData(int port_no, QValueList<SortablePoint>)
 */
void EffectFrame::setPolylineData(int port_no, QValueList<SortablePoint> _poly)
{
    getPortFrame(port_no)->setPolylineData(_poly);
}


/*!
    \fn EffectFrame::updateDrawModeButton()
 */
void EffectFrame::updateDrawModeButton()
{
    if(stack->visibleWidget()){
        if (((EffectPortFrame*)stack->visibleWidget())->hasSpline())
            changeDrawMode(EffectPortFrame::DRAW_MODE_SPLINES);
        else if(((EffectPortFrame*)stack->visibleWidget())->hasPolyline())
            changeDrawMode(EffectPortFrame::DRAW_MODE_POLYLINES);
    }
}


/*!
    \fn EffectFrame::reinitLADSPAValues()
 */
void EffectFrame::reinitLADSPAValues()
{
    for (QPtrList<EffectPortFrame>::Iterator it=portFrames.begin();
        it!=portFrames.end();++it){
            (*it)->reinitLADSPAValues();
            (*it)->update();
    }
}
