#include <QStatusBar>
#include <QClipboard>
#include <QMimeData>

#include "QFitsMainWindow.h"
#include "QFitsMainView.h"
#include "QFitsSingleBuffer.h"
#include "QFitsMultiBuffer.h"
#include "QFitsBaseWidget.h"
#include "QFitsWedge.h"
#include "QFitsMarkers.h"
#include "QFitsToolBar.h"
#include "QFitsCubeSpectrum.h"
#include "QFitsViewingTools.h"
#include "fits.h"

QFitsBaseWidget::QFitsBaseWidget(QFitsBaseBuffer *bb)
                                : QWidget(bb)
{
    myBuffer = NULL;
    QFitsSingleBuffer *sb = dynamic_cast<QFitsSingleBuffer*>(bb);
    if (sb != NULL) {
        myBuffer = sb;
    }


    connect(this, SIGNAL(statusbartext(const QString &)),
            fitsMainWindow->statusBar(), SLOT(showMessage(const QString &)));

    setGeometry(0, 0,
                fitsMainWindow->main_view->size().width(),
                fitsMainWindow->main_view->size().height());

    movieSpeed = 200;
    movieTimer = new QTimer(this);
    connect(movieTimer, SIGNAL(timeout()),
            fitsMainWindow->mytoolbar->cubeImageSlice, SLOT(stepUp()));
}

QFitsBaseWidget::~QFitsBaseWidget() {
}

std::string QFitsBaseWidget::getBufferIndex() {
    return fitsMainWindow->main_view->getCurrentBufferIndex();
}

QFitsSingleBuffer* QFitsBaseWidget::getMyBuffer() {
    return myBuffer;
}

QFitsSingleBuffer* QFitsBaseWidget::getBuffer(std::string index) {
    // AA TODO: enhance this...
    QFitsSingleBuffer *sb = dynamic_cast<QFitsSingleBuffer*>
                                              (fitsMainWindow->main_view->getBuffer(index));
    return sb;
}

// Alex: Achtung geht im Moment nur für QFitsSingleBuffer und nicht für
// QFitsMultiBuffer
void QFitsBaseWidget::calculateScaling(Fits *work) {
    myBuffer->calculateMinMax(work);
    Fits tmp;
    tmp.copy(*work);
    tmp.normub(*work, myBuffer->getImageMinValue(), myBuffer->getImageMaxValue(), myBuffer->getImageScalingMethod());
}

void QFitsBaseWidget::enterBuffer() {
    if (myBuffer != NULL) {
        bool locked = false;
        if (myBuffer->isMultiBufferChild()) {
            // set Min/Max even if imageMin/MaxValue are disabled
            if (!myBuffer->isEmptyPrimary()) {
                fitsMainWindow->mytoolbar->updateImageMinMax(myBuffer);
                if (myBuffer->getDpData()->fvalue->Naxis(3) > 1) {
                    fitsMainWindow->mytoolbar->updateSpecMinMaxY(myBuffer);
                }
            }
        }
        locked = (myBuffer->getLockedSingleBuffer() != NULL);

        if (!locked) {
            fitsMainWindow->setActualSB(myBuffer);
            myBuffer->getCursorMarkers()->setCenter(myBuffer, 0, 0);
        }

        if (fitsMainWindow->spectrum->isVisible()) {
            fitsMainWindow->spectrum->changeWorkArray();
        }

        // set caption for multi extension files
        // (regardless of locked buffer)
        int index = myBuffer->indexOfMultiBuffer();
        if (index >= 0) {
            QString caption;
            if (myBuffer->isMultiBufferChild()) {
                caption = myBuffer->getMyMultiBuffer()->getAppearance().windowTitle;
            } else {
                caption = myBuffer->getAppearance().windowTitle;
            }
            if (!myBuffer->getDpData()->showAsTable()) {
                if (index == 0) {
                    caption.append(", primary");
                } else if (index > 0) {
                    caption.append(", ext #");
                    if (myBuffer->getExtensionIndicesVec().size() == 1) {
                        caption.append(QString::number(index));
                    } else {
                        caption.append(myBuffer->getExtensionIndicesString());
                    }

                    char extname[80];
                    QReadLocker locker(&buffersLock);
                    if ((myBuffer->getDpData()->type == typeFits) &&
                        (myBuffer->getDpData()->fvalue->GetStringKey("EXTNAME", extname)))
                    {
                        caption.append(", ");
                        caption.append(extname);
                    }
                }
            } else {
                int pos = caption.indexOf(", table #");
                if (pos != -1) {
                    caption.chop(caption.size() - pos);
                }

                caption.append(", ext #");
                caption.append(QString::number(index));

                if (caption.size() > 0) {
                    caption += ", col: " + QString::number(index+1);
                }
            }
            fitsMainWindow->setWindowTitle(caption);
        }
    }
}

void QFitsBaseWidget::leaveBuffer() {
    if (myBuffer != NULL) {
        if (myBuffer->isMultiBufferChild()) {

            // by default set actualSB to NULL
            QFitsSingleBuffer *sb = NULL;

            // now set it to markedSB, if set
            sb = myBuffer->getMyMultiBuffer()->getMarkedSingleBuffer();

            if (myBuffer->getLockedSingleBuffer() != NULL) {
                // oh, the SB we left right now is even locked!
                // this is stronger than a marked buffer, so we set the lockedSB as actual
                sb = myBuffer->getMyMultiBuffer()->getLockedSingleBuffer();
            }

            fitsMainWindow->setActualSB(sb);

            if (sb == NULL) {
                fitsMainWindow->mytoolbar->updateImageMinMax(NULL);
                fitsMainWindow->mytoolbar->updateSpecMinMaxY(NULL);
                fitsMainWindow->spectrum->resetRangeControl();
                fitsMainWindow->mytoolbar->enableControlsView1D(false);
            }
        }

        // set caption for multi extension files
        // (regardless of locked buffer)
        int index = myBuffer->indexOfMultiBuffer();
        if (index >= 0) {
            QString caption;
            if (myBuffer->isMultiBufferChild()) {
                caption = myBuffer->getMyMultiBuffer()->getAppearance().windowTitle;
            } else {
                caption = myBuffer->getAppearance().windowTitle;
            }
            fitsMainWindow->setWindowTitle(caption);
        }
    }
    fitsMainWindow->viewingtools->magnifier->clear();
}

void QFitsBaseWidget::setMovieSpeed(int speed) {
    movieSpeed = speed;
    if (movieTimer->isActive()) {
        movieTimer->setInterval(movieSpeed);
    }
}

void QFitsBaseWidget::enableMovie(bool enable) {
    if (enable) {
        movieTimer->start(movieSpeed);
    } else {
        movieTimer->stop();
    }
}

void QFitsBaseWidget::copyImage(int) {
    QReadLocker locker(&buffersLock);
    if ((myBuffer->getDpData()->type == typeFits) &&
        (myBuffer->getDpData()->fvalue->Naxis(0) == 1))
    {
        Fits *f = myBuffer->getDpData()->fvalue;
        QMimeData *copyData = new QMimeData();
        QStringList entries;
        double  crval = f->getCRVAL(1),
                crpix = f->getCRPIX(1),
                cdelt = f->getCDELT(1);
        bool logwave = f->isAxisLog(1);

        if (cdelt > 0.0) {
            for (long i = 0; i < f->Naxis(1); i++) {
                entries << QString::number(pixwave(i+1, crpix, crval, cdelt, logwave)) + "\t" + QString::number(f->ValueAt(i));
            }
        } else {
            for (long i = 0, j = f->Naxis(1)-1; i < myBuffer->getDpData()->fvalue->Naxis(1); i++, j--) {
                entries << QString::number(pixwave(i+1, crpix, crval, cdelt, logwave)) + "\t" + QString::number(f->ValueAt(i));
            }
        }
        copyData->setText(entries.join("\n"));
        copyData->setImageData(grab());
        QApplication::clipboard()->setMimeData(copyData);
    } else {
        QApplication::clipboard()->setPixmap(grab());
    }
}
