/* -*- c++ -*- */
/*
 * Copyright 2014 Communications Engineering Lab, KIT.
 *
 * This 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 3, or (at your option)
 * any later version.
 *
 * This software 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 software; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#include "spectrogram_plot.h"
#include <iostream>
#include <stdexcept>

namespace gr {
namespace radar {

spectrogram_plot::spectrogram_plot(int interval,
                                   int vlen,
                                   std::vector<float>* buffer,
                                   std::string label_x,
                                   std::string label_y,
                                   std::string label,
                                   std::vector<float> axis_x,
                                   std::vector<float> axis_y,
                                   std::vector<float> axis_z,
                                   bool autoscale_z,
                                   QWidget* parent)
    : QWidget(parent)
{
    d_interval = interval;
    d_vlen = vlen;
    d_buffer = buffer;
    d_axis_x = axis_x;
    d_axis_y = axis_y;
    d_axis_z = axis_z;
    d_autoscale_z = autoscale_z;

    // Setup GUI
    resize(QSize(600, 600));

    d_plot = new QwtPlot(this);               // make main plot
    d_spectrogram = new QwtPlotSpectrogram(); // make spectrogram
    d_spectrogram->attach(d_plot);            // attach spectrogram to plot

    d_data = new QwtMatrixRasterData(); // make data structure

    // Setup colormap
    d_colormap = new QwtLinearColorMap(Qt::darkCyan, Qt::red);
    d_colormap->addColorStop(0.25, Qt::cyan);
    d_colormap->addColorStop(0.5, Qt::green);
    d_colormap->addColorStop(0.75, Qt::yellow);

    d_spectrogram->setColorMap(d_colormap);

    // Plot axis and title
    std::string label_title = "Spectrogram Plot: ";
    label_title.append(label_x);
    label_title.append("/");
    label_title.append(label_y);
    if (label != "") {
        label_title.append(" (");
        label_title.append(label);
        label_title.append(")");
    }
    d_plot->setTitle(QwtText(label_title.c_str()));
    d_plot->setAxisTitle(QwtPlot::xBottom, label_x.c_str());
    d_plot->setAxisTitle(QwtPlot::yLeft, label_y.c_str());

    // Do replot
    d_plot->replot();

    // Setup timer and connect refreshing plot
    d_timer = new QTimer(this);
    connect(d_timer, SIGNAL(timeout()), this, SLOT(refresh()));
    d_timer->start(d_interval);
}

spectrogram_plot::~spectrogram_plot() {}

void spectrogram_plot::resizeEvent(QResizeEvent* event)
{
    d_plot->setGeometry(0, 0, this->width(), this->height());
}

void spectrogram_plot::refresh()
{
    // Fetch new data and push to matrix
    d_plot_data.clear();
    d_plot_data.resize(d_buffer->size());
    float maximum, minimum; // get maximum and minimum
    if (d_buffer->size() != 0) {
        maximum = (*d_buffer)[0];
        minimum = (*d_buffer)[0];
    } else
        throw std::runtime_error("data buffer has size zero");

    for (int k = 0; k < d_buffer->size(); k++) {
        d_plot_data[k] = (*d_buffer)[k];
        if (d_plot_data[k] < minimum)
            minimum = d_plot_data[k];
        if (d_plot_data[k] > maximum)
            maximum = d_plot_data[k];
    }
    if (std::isnan(minimum) || std::isnan(maximum))
        throw std::runtime_error("minimum or maximum for z axis is NaN");

    // Get rows and columns
    int columns, rows;
    columns = d_vlen;
    rows = d_buffer->size() / d_vlen;

    // Fill data in spectrogram
    d_data->setValueMatrix(d_plot_data, columns);
    d_data->setInterval(Qt::XAxis, QwtInterval(d_axis_x[0], d_axis_x[1]));
    d_data->setInterval(Qt::YAxis, QwtInterval(d_axis_y[0], d_axis_y[1]));
    if (d_autoscale_z) {
        d_data->setInterval(Qt::ZAxis, QwtInterval(minimum, maximum));
    } else {
        d_data->setInterval(Qt::ZAxis, QwtInterval(d_axis_z[0], d_axis_z[1]));
    }

    d_spectrogram->setData(d_data);

    // Set colorbar
    d_scale = d_plot->axisWidget(QwtPlot::yRight);
    d_scale->setColorBarEnabled(true);
    d_scale->setColorBarWidth(20);
    if (d_autoscale_z) {
        d_scale->setColorMap(QwtInterval(minimum, maximum), d_colormap);
        d_plot->setAxisScale(QwtPlot::yRight, minimum, maximum);
    } else {
        d_scale->setColorMap(QwtInterval(d_axis_z[0], d_axis_z[1]), d_colormap);
        d_plot->setAxisScale(QwtPlot::yRight, d_axis_z[0], d_axis_z[1]);
    }
    d_plot->enableAxis(QwtPlot::yRight);

    // Do replot
    d_plot->replot();
}

} // namespace radar
} // namespace gr
