/***************************************************************************
    File                 : MultiPeakFitTool.cpp
    Project              : SciDAVis
    --------------------------------------------------------------------
    Copyright            : (C) 2006,2007 by Ion Vasilief,
                           Tilman Benkert, Knut Franke
    Email (use @ for *)  : ion_vasilief*yahoo.fr, thzs*gmx.net,
                           knut.franke*gmx.de
    Description          : Plot tool for doing multi-peak fitting.

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

/***************************************************************************
 *                                                                         *
 *  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., 51 Franklin Street, Fifth Floor,                    *
 *   Boston, MA  02110-1301  USA                                           *
 *                                                                         *
 ***************************************************************************/
#include "MultiPeakFitTool.h"
#include "ApplicationWindow.h"
#include "DataPickerTool.h"
#include "Plot.h"
#include <qwt_plot_curve.h>
#include <QApplication>

MultiPeakFitTool::MultiPeakFitTool(Graph *graph, ApplicationWindow *app,
                                   MultiPeakFit::PeakProfile profile, int num_peaks,
                                   const QObject *status_target, const char *status_slot)
    : PlotToolInterface(graph), d_profile(profile), d_num_peaks(num_peaks)
{
    d_selected_peaks = 0;
    d_curve = 0;

    d_fit = new MultiPeakFit(app, d_graph, d_profile, d_num_peaks);
    d_fit->enablePeakCurves(app->generatePeakCurves);
    d_fit->setPeakCurvesColor(app->peakCurvesColor);
    d_fit->generateFunction(app->generateUniformFitPoints, app->fitPoints);

    if (status_target)
        connect(this, SIGNAL(statusText(const QString &)), status_target, status_slot);
    d_picker_tool = new DataPickerTool(d_graph, app, DataPickerTool::Display, this,
                                       SIGNAL(statusText(const QString &)));
    connect(d_picker_tool, SIGNAL(selected(QwtPlotCurve *, int)), this,
            SLOT(selectPeak(QwtPlotCurve *, int)));
    d_graph->plotWidget()->canvas()->grabMouse();
    emit statusText(tr("Move cursor and click to select a point and double-click/press 'Enter' to "
                       "set the position of a peak!"));
}

MultiPeakFitTool::~MultiPeakFitTool()
{
    if (d_picker_tool)
        delete d_picker_tool;
    if (d_fit)
        delete d_fit;
    d_graph->plotWidget()->canvas()->unsetCursor();
}

void MultiPeakFitTool::selectPeak(QwtPlotCurve *curve, int point_index)
{
    // TODO: warn user
    if (!curve || (d_curve && d_curve != curve))
        return;
    d_curve = curve;

    d_fit->setInitialGuess(3 * d_selected_peaks, curve->y(point_index));
    d_fit->setInitialGuess(3 * d_selected_peaks + 1, curve->x(point_index));

    QwtPlotMarker *m = new QwtPlotMarker();
    m->setLineStyle(QwtPlotMarker::VLine);
    m->setLinePen(QPen(Qt::green, 2, Qt::DashLine));
    m->setXValue(curve->x(point_index));
    d_graph->plotWidget()->insertMarker(m);
    d_graph->plotWidget()->replot();

    d_selected_peaks++;
    if (d_selected_peaks == d_num_peaks)
        finalize();
    else
        emit statusText(tr("Peak %1 selected! Click to select a point and double-click/press "
                           "'Enter' to set the position of the next peak!")
                                .arg(QString::number(d_selected_peaks)));
}

void MultiPeakFitTool::finalize()
{
    delete d_picker_tool;
    d_picker_tool = NULL;
    d_graph->plotWidget()->canvas()->releaseMouse();

    if (d_fit->setDataFromCurve(d_curve->title().text())) {
        QApplication::setOverrideCursor(Qt::WaitCursor);
        d_fit->fit();
        delete d_fit;
        d_fit = NULL;
        QApplication::restoreOverrideCursor();
    }

    // remove peak line markers
    QList<int> mrks = d_graph->plotWidget()->markerKeys();
    int n = (int)mrks.count();
    for (int i = 0; i < d_num_peaks; i++)
        d_graph->plotWidget()->removeMarker(mrks[n - i - 1]);

    d_graph->plotWidget()->replot();

    d_graph->setActiveTool(NULL);
    // attention: I'm now deleted. Maybe there is a cleaner solution...
}
