#include <QGridLayout>
#include <QScrollBar>
#include <QResizeEvent>

#include <gsl/gsl_math.h>

#include "QFitsMainWindow.h"
#include "QFitsMultiBuffer.h"
#include "QFitsSingleBuffer.h"
#include "QFitsMainView.h"
#include "QFitsBaseWidget.h"
#include "QFitsWidget2D.h"
#include "QFitsScroller.h"
#include "QFitsCubeSpectrum.h"
#include "QFitsViewingTools.h"
#include "QFitsWidgetTable.h"
#include "QFitsWedge.h"
#include "fits.h"
#include "qtdpuser.h"

QFitsMultiBuffer::QFitsMultiBuffer(QFitsMainView *main_view,
                                   dpuserType *dpt,
                                   int dbg, QString dbg_upper)
                                  : QFitsBaseBuffer(main_view)
{
    grid                    = NULL;
    gridWidget              = new QWidget(this);
    mtv_tableMulti          = NULL;

    init(dpt, dbg, dbg_upper);
}

QFitsMultiBuffer::QFitsMultiBuffer(QFitsMultiBuffer *mb,
                                   dpuserType *dpt,
                                   int dbg, QString dbg_upper)
                                  : QFitsBaseBuffer(mb)
{
    grid                    = NULL;
    gridWidget              = new QWidget(this);
    mtv_tableMulti          = NULL;

    init(dpt, dbg, dbg_upper);
}

QFitsMultiBuffer::~QFitsMultiBuffer() {
    if (!bufferList.isEmpty()) {
        for (int i = 0; i < bufferList.size(); i++) {
            QFitsBaseBuffer *bb = bufferList.takeAt(i);
            delete bb;
        }
    }

    if (grid != NULL) {
        delete grid; grid = NULL;
    }

    if (gridWidget != NULL) {
        delete gridWidget; gridWidget = NULL;
    }

    if (mtv_tableMulti != NULL) {
        delete mtv_tableMulti; mtv_tableMulti = NULL;
    }
}

void QFitsMultiBuffer::init(dpuserType *dpt, int dbg, QString dbg_upper) {
    QFitsBaseBuffer::init(dbg, dbg_upper);
    dp_debug("INIT MB    (%p) %s\n", this, dbg_level.toStdString().c_str());

    dpData = dpt;

    hasChildMB              = false;
    cubeSpecHomogenSB       = false;
    hasMixedView            = false;

    if (mtv_tableMulti != NULL) {
        delete mtv_tableMulti; mtv_tableMulti = NULL;
    }

    if (grid != NULL) {
        delete grid;
    }
    grid = new QGridLayout(gridWidget);
    grid->setSpacing(3);
    grid->setContentsMargins(3, 3, 3, 3);

    int listSize    = dpData->dparrvalue->size(),
        nr_columns  = ceil(sqrt(listSize)),
        row         = 0,
        column      = 0,
        nr1Dbuffers = 0;
    for (int i = 0; i < listSize; i++) {
        if (bufferList.size() > i) {
            QFitsSingleBuffer *sb  = dynamic_cast<QFitsSingleBuffer*>(bufferList.at(i));
            QFitsMultiBuffer  *mb  = dynamic_cast<QFitsMultiBuffer*>(bufferList.at(i));
            if (sb != NULL) {
                if ((dpData->dparrvalue->at(i)->type != sb->getDpData()->type) ||
                    ((dpData->dparrvalue->at(i)->type == typeFits) && (sb->getDpData()->fvalue != dpData->dparrvalue->at(i)->fvalue)) ||
                    ((dpData->dparrvalue->at(i)->type == typeStrarr) && (sb->getDpData()->arrvalue != dpData->dparrvalue->at(i)->arrvalue))
                   )
                {
                    delete bufferList.at(i);
                    bufferList.replace(i, new QFitsSingleBuffer(this, dpData->dparrvalue->at(i), i, dbg_level));
                }
            } else if (mb != NULL) {
                if ((dpData->dparrvalue->at(i)->type == typeDpArr) &&
                    (mb->getDpData()->dparrvalue != dpData->dparrvalue->at(i)->dparrvalue))
                {
                    delete bufferList.at(i);
                    bufferList.replace(i, new QFitsMultiBuffer(this, dpData->dparrvalue->at(i), i, dbg_level));
                    hasChildMB = true;
                }
            }
        } else {
            if (dpData->dparrvalue->at(i)->type == typeDpArr) {
                // create new QFitsMultiBuffer
                bufferList.append(new QFitsMultiBuffer(this, dpData->dparrvalue->at(i), i, dbg_level));
                hasChildMB = true;
            } else {
                // create new QFitsSingleBuffer with according Fits or dpStringList
                bufferList.append(new QFitsSingleBuffer(this, dpData->dparrvalue->at(i), i, dbg_level));
            }
        }

        grid->addWidget(bufferList.at(i), row, column++);

        if (column == nr_columns) {
            row++;
            column = 0;
        }

        QFitsSingleBuffer *sb = dynamic_cast<QFitsSingleBuffer*>(bufferList.at(i));
        if (sb != NULL) {
            if (sb->Naxis(0) == 1) {
                nr1Dbuffers++;
            }
            if (sb->getDpData()->type == typeFits) {
                if (sb->getDpData()->fvalue->extensionType == EMPTY) {
                    // do nothing, empty primary is ignored here
                } else {
                    if (!hasSpectrum && (sb->Naxis(0) == 1)) {
                        hasSpectrum = true;
                    }
                    if (!hasImage && (sb->Naxis(0) == 2)) {
                        hasImage = true;
                    }
                    if (!hasCube && (sb->Naxis(0) == 3)) {
                        hasCube = true;
                    }
                }
            } else if (sb->getDpData()->type == typeStrarr) {
                hasStrArr = true;
            }
        } else {
            QFitsMultiBuffer *mb = dynamic_cast<QFitsMultiBuffer*>(bufferList.at(i));
            if (!hasSpectrum && mb->getHasSpectrum()) {
                hasSpectrum = true;
            }
            if (!hasImage && mb->getHasImage()) {
                hasImage = true;
            }
            if (!hasCube && mb->getHasCube()) {
                hasCube = true;
            }
            if (!hasStrArr && mb->getHasStrArr()) {
                hasStrArr = true;
            }
        }
    }

    if ((hasSpectrum && hasImage) ||
        (hasSpectrum && hasCube) ||
        (hasImage && hasCube))
    {
        hasMixedView = true;
    }

    checkCubeSpecHomogenSB();

    if (cubeSpecHomogenSB) {
        for (int i = 0; i < bufferList.size(); i++) {
            if (!dynamic_cast<QFitsSingleBuffer*>(bufferList.at(i))->isEmptyPrimary()) {
                setCubeSpecOrientation(bufferList.at(i)->getCubeSpecOrientation(), false);
                setCubeCenter(bufferList.at(i)->QFitsBaseBuffer::getCubeCenter(getCubeSpecOrientation()), getCubeSpecOrientation(), false);
                setLineWidth(bufferList.at(i)->getLineWidth(getCubeSpecOrientation()), getCubeSpecOrientation(), false);
                setLineCont1Center(bufferList.at(i)->QFitsBaseBuffer::getLineCont1Center());
                setLineCont1Width(bufferList.at(i)->QFitsBaseBuffer::getLineCont1Width());
                setLineCont2Center(bufferList.at(i)->QFitsBaseBuffer::getLineCont2Center());
                setLineCont2Width(bufferList.at(i)->QFitsBaseBuffer::getLineCont2Width());
                break;
            }
        }
    }

    ResetSpectrum();

    if (nr1Dbuffers == listSize) {
        bufAppearance.hideWedge = true;
    }
    if (dpData->showAsTable()) {
        viewMode = ViewTable;
    } else {
        viewMode = ViewImage;
    }

    mtv_tableMulti = new QFitsWidgetTable(this);
}

// checks if all child SB's are of typeFits with the same WCS in spectral dimension
// for the moment being only interesting with cubes
void QFitsMultiBuffer::checkCubeSpecHomogenSB() {
    cubeSpecHomogenSB = false;

    // check if all childs are SB
    for (int i = 0; i < bufferList.size(); i++) {
        if (dynamic_cast<QFitsSingleBuffer*>(bufferList.at(i)) == NULL) {
            return;
        }
    }

    // check if all SBs are of type typeFits
    for (int i = 0; i < bufferList.size(); i++) {
        if (bufferList.at(i)->getDpData()->type != typeFits) {
            return;
        }
    }

    // skip eventual empty primary
    int i = 0;
    if (bufferList.at(i)->getDpData()->fvalue->extensionType == EMPTY) {
        i++;
    }

    // get dimensions and WCS of first IMAGE
    int     tmp_naxis[4];
    double  tmp_crval,
            tmp_crpix,
            tmp_cdelt;
    for (int j = 0; j < 4; j++) {
        tmp_naxis[j] = bufferList.at(i)->getDpData()->fvalue->Naxis(j);
    }

    tmp_crval = bufferList.at(i)->getDpData()->fvalue->getCRVAL(3);
    tmp_crpix = bufferList.at(i)->getDpData()->fvalue->getCRPIX(3);
    tmp_cdelt = bufferList.at(i)->getDpData()->fvalue->getCDELT(3);
    i++;
    if (i >= bufferList.size()) {
        // only one valide IMAGE (typeFits)
        cubeSpecHomogenSB = true;
        return;
    }

    // check if dimensions and WCS are the same for all SBs
    if (!dpData->showAsTable()) {
        for (; i < bufferList.size(); i++) {
            for (int j = 0; j < 4; j++) {
                if (tmp_naxis[j] != bufferList.at(i)->getDpData()->fvalue->Naxis(j)) {
                    return;
                }
            }

            if ((fabs(tmp_crval - bufferList.at(i)->getDpData()->fvalue->getCRVAL(3)) > 1e-6) ||
                (fabs(tmp_crpix - bufferList.at(i)->getDpData()->fvalue->getCRPIX(3)) > 1e-6) ||
                (fabs(tmp_cdelt - bufferList.at(i)->getDpData()->fvalue->getCDELT(3)) > 1e-6))
            {
                return;
            }
        }
    } else {
        // we assume here that tables have all same length
    }
    cubeSpecHomogenSB = true;
}

void QFitsMultiBuffer::ResetSpectrum() {
    if (cubeSpecHomogenSB) {
        // now all SBs are initialized,
        // assert that according values are set as well in MB
        getFirstImageBuffer()->ResetSpectrum();
        specChannelMaxX = getFirstImageBuffer()->getSpecChannelMaxX();
    } else {
        specChannelMinX     = 0;
        specChannelMaxX     = 0;
        specPhysMinY        = 0.0;
        specPhysMaxY        = 0.0;
        specPhysMinX        = 0.;
        specPhysMaxX        = 0.;
    }
}

int QFitsMultiBuffer::indexOf(QFitsBaseBuffer *bb) {
    return bufferList.indexOf(bb);
}

void QFitsMultiBuffer::resizeEvent(QResizeEvent *r) {
//dp_debug("QFitsMultiBuffer::resizeEvent() [%p, MB%s] (%d, %d)\n", this, dbg_level.toStdString().c_str(), r->size().width(), r->size().height()); fflush(stdout);
    if ((viewMode == ViewTable) && !hasChildMB) {
        mtv_tableMulti->setGeometry(0, 0, r->size().width(), r->size().height());
    } else {
//        dp_debug("    --> GRID\n"); fflush(stdout);
        gridWidget->setGeometry(0, 0, r->size().width(), r->size().height());
    }
}

void QFitsMultiBuffer::saveFits() {
    QString selectedFilter;
    QString filename = QFileDialog::getSaveFileName(this,
                                                    "QFitsView - Save as FITS",
                                                    settings.lastSavePath,
                                                    "*.fits;;*",
                                                    &selectedFilter);
    if (!filename.isNull() &&
        (dpData->type == typeDpArr) &&
        buffersLock.tryLockForRead())
    {
        selectedFilter.remove(0,1);
        if (!filename.endsWith(selectedFilter)) {
            filename += selectedFilter;
        }

        if (dpData->dparrvalue->at(0)->type == typeFits) {
            dpData->dparrvalue->at(0)->fvalue->WriteFITS(filename.toStdString().c_str());
            for (int i = 1; i < dpData->dparrvalue->size(); i++) {
                if (dpData->dparrvalue->at(i)->type == typeFits) {
                    dpData->dparrvalue->at(i)->fvalue->WriteFITSExtension(filename.toStdString().c_str());
                }
            }
        }

        buffersLock.unlock();
        QFileInfo finfo(filename);
        settings.lastSavePath = finfo.absoluteDir().path();
        settings.lastSavePath.replace("\\", "/");
    }
}

void QFitsMultiBuffer::activateBuffer() {
dp_debug("QFitsMultiBuffer::activateBuffer()");
    QFitsBaseBuffer::activateBuffer();
    if (viewMode == ViewTable) {
        fitsMainWindow->spectrum->changeWorkArray();
        fitsMainWindow->updateScaling();
        mtv_tableMulti->restoreState();
    } else {
        if ((viewMode == ViewImage) && getHasSpectrum()) {
            // This need in fact only to be done when an extension is displayed initially as ViewTable
            // and the view is afterwards changed to Viewimage
            for (int i = 0; i < bufferList.size(); i++) {
                if (bufferList.at(i)->getHasSpectrum()) {
                    QFitsSingleBuffer *sb = dynamic_cast<QFitsSingleBuffer*>(bufferList.at(i));
                    if (sb != NULL) {
                        sb->activateBuffer();
                    }
                }
            }
        }

        // set now active first QFitsSingleBuffer
        QFitsSingleBuffer *sb = getFirstImageBuffer();
        if (sb != NULL) {
            sb->activateBuffer();
        }
    }
    setFocus();
}

BufferAppearance QFitsMultiBuffer::updateAppearance() {
    QFitsBaseBuffer::updateAppearance();

    for (int i = 0; i < bufferList.size(); i++) {
        bufferList.at(i)->updateAppearance();
    }

    if (cubeSpecHomogenSB) {
        bufAppearance = getFirstImageBuffer()->getAppearance();
    } else {
        if (hasSpectrum && !hasImage && !hasCube) {
            bufAppearance.enableColourmapMenu = false;
            bufAppearance.enableScaleMenu = false;
            bufAppearance.enableZoomMenu = false;
        } else {
            bufAppearance.enableColourmapMenu = true;
            bufAppearance.enableScaleMenu = true;
            bufAppearance.enableZoomMenu = true;
        }
    }

    bufAppearance.enableImredMenu = false;
    bufAppearance.enableArithmeticButtons = false;

    dpViewMode tmpViewMode = viewMode;
    if (hasChildMB) {
        tmpViewMode = ViewImage;
    }
    if (tmpViewMode == ViewTable) {
        // show TableView
        gridWidget->hide();
        if (mtv_tableMulti == NULL) {
            mtv_tableMulti = new QFitsWidgetTable(this);
        }
        mtv_tableMulti->show();

        QFitsTableView *tv = mtv_tableMulti->getTableView();
        if (tv != NULL) {
            if (tv->doPlotData()) {
                bufAppearance.hideSpectrum = false;
            } else {
                bufAppearance.hideSpectrum = true;
            }
        } else {
            bufAppearance.hideSpectrum = true;
        }
        bufAppearance.hideViewingtools = false;
        bufAppearance.hideWedge = true;
    } else {
        // show GridView
        if (mtv_tableMulti != NULL) {
            mtv_tableMulti->hide();
        }
        gridWidget->show();

        bufAppearance.hideSpectrum = true;
        bufAppearance.hideViewingtools = true;
        bufAppearance.hideWedge = true;
        bufAppearance.showToolbarOrientation  = false;
        //if (cubeSpecHomogenSB && hasCube) {
        if (hasCube) {
            bufAppearance.showToolbarMovie = true;
        } else {
            bufAppearance.showToolbarMovie = false;
        }
//        if (hasMixedView) {
//            bufAppearance.showToolbarScaling = false;
//        }
        switch (viewMode) {
        case ViewImage:
            if (hasSpectrum) {
                bufAppearance.showToolbarZoom         = false;
                bufAppearance.showToolbarCube         = false;
            }
            if (hasImage) {
                bufAppearance.showToolbarZoom         = true;
                bufAppearance.showToolbarCube         = false;
                if (settings.showViewingTools != 0) {
                    bufAppearance.hideViewingtools = false;
                    bufAppearance.hideWedge = false;
                }
            }
            if (hasCube) {
                bufAppearance.showToolbarZoom         = true;
                bufAppearance.showToolbarCube         = false;
                bufAppearance.hideSpectrum = false;
                if (settings.showViewingTools != 0) {
                    bufAppearance.hideViewingtools = false;
                    bufAppearance.hideWedge = false;
                }
            }
            break;
        case ViewWiregrid:
        case ViewContour:
        case ViewTable:
            break;
        default:
            break;
        }
    }

    // handle focus
    if (fitsMainWindow->bufferChangedByKey) {
        setFocus();
        fitsMainWindow->bufferChangedByKey = false;
    }

    fitsMainWindow->viewActions->actions()[viewMode]->setChecked(true);

    return bufAppearance;
}

int QFitsMultiBuffer::getPos(QFitsSingleBuffer *sb) {
    int ret = -1;
    for (int i = 0; i < bufferList.size(); i++) {
        if (bufferList.at(i) == sb) {
            ret = i;
            break;
        }
    }
    return ret;
}

void QFitsMultiBuffer::setMouseTrackingView(bool track, bool traceUp) {
    if (traceUp && isMultiBufferChild()) {
        myMultiBuffer->setMouseTrackingView(track, traceUp);
    } else {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setMouseTrackingView(track, false);
        }
    }
}

void QFitsMultiBuffer::updateHomogenSB() {
    if (cubeSpecHomogenSB) {
        setXRange();
//        for (int i = 0; i < bufferList.size(); i++) {
//            bufferList.at(i)->getState()->update();
//        }
    }
}

void QFitsMultiBuffer::ChangeWidgetState(dpViewMode mode) {
    for (int i = 0; i < bufferList.size(); i++) {
        bufferList.at(i)->ChangeWidgetState(mode);
    }

    viewMode = mode;
}

void QFitsMultiBuffer::zoomTextChanged(double zoomValue, FitZoom fz) {
    if (viewMode != ViewTable) {
        if (fz != FitZoomNone) {
            // "Fit window", "Fit width" or "Fit height"

            // this is only needed because the widgets (hsplitter, spectrum, qtdpuser)
            // in QFitsMainWindow can't be put into a QVBoxLayout, they are in a QSplitter.
            // Furthermore spectrum is not always visible, specially at startup.
            // I think with a layout, this would be more straightforward
            int wedgeSpectrumCorrection = 0;
            if (!fitsMainWindow->zoomCorr_ComboZoomTriggered) {
                if (hasImage || hasCube) {
                    wedgeSpectrumCorrection += fitsMainWindow->main_view->getWedge()->minimumHeight();
                }

                if (hasCube) {
                    if (!fitsMainWindow->zoomCorr_spectrumVisible) {
                        wedgeSpectrumCorrection += fitsMainWindow->spectrum->minimumHeight()+4;
                    }
                }
                if (hasImage && !hasCube) {
                    if (fitsMainWindow->zoomCorr_spectrumVisible) {
                        wedgeSpectrumCorrection -= fitsMainWindow->spectrum->minimumHeight()+4;
                    }
                }
            }
            fitsMainWindow->zoomCorr_ComboZoomTriggered = false;

            int nrCol = grid->columnCount(),
                nrRow = grid->rowCount(),
                w = (gridWidget->width()  - grid->contentsMargins().right() - grid->contentsMargins().left() - (nrCol-1)*grid->spacing()) / nrCol,
                h = (gridWidget->height() - wedgeSpectrumCorrection - grid->contentsMargins().bottom() - grid->contentsMargins().top() - (nrRow-1)*grid->spacing()) / nrRow;

            zoomValue = DBL_MAX;
            if (cubeSpecHomogenSB) {
                zoomValue = getFirstImageBuffer()->calcZoomFitWindow(w, h, fz);
            } else {
                for (int i = 0; i < bufferList.size(); i++) {
                    QFitsSingleBuffer *sb = dynamic_cast<QFitsSingleBuffer*>(bufferList.at(i));
                    if ((sb != NULL) &&
                        (sb->getDpData()->type == typeFits) &&
                        (sb->getDpData()->fvalue->extensionType != EMPTY))
                    {
                        double t = sb->calcZoomFitWindow(w, h, fz);
                        if (t < zoomValue) {
                            zoomValue = t;
                        }
                    }
                }
            }
            fitsMainWindow->mytoolbar->setZoomTextCombo(zoomValue);
        }
        setZoomWidget(zoomValue);
    }
}

void QFitsMultiBuffer::showCubePlot() {
    if (viewMode != ViewTable) {
        fitsMainWindow->mytoolbar->movieButton->setChecked(false);
        // show QFitsCubeSpectrum if at least one FITS-cube is present
        // in this QFitsMultiBuffer
        for (int i = 0; i < dpData->dparrvalue->size(); i++) {
            if (dpData->dparrvalue->at(i)->type == typeFits) {
                if (dpData->dparrvalue->at(i)->fvalue->Naxis(3) >= 2) {
                    bufAppearance.hideSpectrum = false;
                    break;
                }
            }
        }
    }
}

void QFitsMultiBuffer::updateLinemapDialog() {
    if (viewMode != ViewTable) {
        fitsMainWindow->getActualSB()->updateLinemapDialog();
    }
}

void QFitsMultiBuffer::setZoomWidget(double zoomValue) {
    if (viewMode != ViewTable) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setZoomWidget(zoomValue);
        }
        zoom = convertZoomDoubleToIndex(zoomValue);
    }
}

void QFitsMultiBuffer::orientationChanged() {
    if (viewMode != ViewTable) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->orientationChanged();
        }
    }
}

void QFitsMultiBuffer::updateScaling() {
    if (viewMode == ViewTable) {
        mtv_tableMulti->updateScaling();
    }/* else {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->updateScaling();
        }
    }*/
    for (int i = 0; i < bufferList.size(); i++) {
        bufferList.at(i)->updateScaling();
    }
}

void QFitsMultiBuffer::setFocus() {
    if (!dpuser_widget->input->hasFocus()) {
        if (viewMode == ViewTable) {
            mtv_tableMulti->getTableView()->setFocus();
        } else {
            // AA: implement correct handling for QFitsMultiBuffer here
            gridWidget->setFocus();
        }
    }
}

void QFitsMultiBuffer::setCubeSpecOrientation(QFV::Orientation o, bool allSB) {
    if ((o == Qt::Vertical) &&
        (dpData->fvalue != NULL) &&
        (dpData->fvalue->Naxis(0) == 1))
    {
        o = QFV::Horizontal;    // set here orientation to dim 1
    }
    cubeSpecOrientation = o;
    if (!hasChildMB && allSB) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setCubeSpecOrientation(o);
        }
    }
}

void QFitsMultiBuffer::setCubeCenter(double c, QFV::Orientation o, bool allSB) {
    if (o == QFV::Default) {
        o = getCubeSpecOrientation();
    }
    cubeCenter[o] = c;
    setDirty(true);
    if (!hasChildMB && allSB) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setCubeCenter(c, o);
        }
    }
}

void QFitsMultiBuffer::setLineWidth(double w, QFV::Orientation o, bool allSB) {
    if (o == QFV::Default) {
        o = getCubeSpecOrientation();
    }
    lineWidth[o] = w;
    setDirty(true);
    if (!hasChildMB && allSB) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setLineWidth(w, o);
        }
    }
}

void QFitsMultiBuffer::setLinemapOptions(bool c1, bool c2, int cen1, int wid1,
                                         int cen2, int wid2, int cen3, int wid3)
{
    if ((viewMode != ViewTable) && !hasChildMB) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setLinemapOptions(c1, c2, cen1, wid1, cen2, wid2, cen3, wid3);
        }
    }
}

void QFitsMultiBuffer::setupColours() {
//    if (viewMode != ViewTable) {
        QVector<QRgb> *colorVec = setActualColortable();

        if (colorVec != NULL) {
            for (int i = 0; i < bufferList.size(); i++) {
                QFitsSingleBuffer *sb = dynamic_cast<QFitsSingleBuffer*>(bufferList.at(i));
                if (sb != NULL) {
                    sb->getImage()->setColorTable(*colorVec);
                    sb->getState()->setupColours();
                }
            }
            delete colorVec;
        }

        fitsMainWindow->updateViewingtools();
        fitsMainWindow->updateWedge();
//    }
}

void QFitsMultiBuffer::setImageScaleRange(dpScaleMode mode) {
    if (viewMode != ViewTable) {
        imageScaleRange = mode;
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setImageScaleRange(mode);
        }
    }
}

void QFitsMultiBuffer::setZoomFactor(double zoomValue) {
    if (viewMode != ViewTable) {
        zoom = zoomValue;
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setZoomFactor(zoomValue);
        }
    }
}

void QFitsMultiBuffer::setCubeMode(dpCubeMode mode, bool allSB) {
    cubeMode = mode;
    if (allSB) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setCubeMode(mode);
        }
    }
}

void QFitsMultiBuffer::setColormap(QAction *action) {
    if (viewMode != ViewTable) {
        colormap = action;
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setColormap(action);
        }
    }
}

void QFitsMultiBuffer::setInvertColormap(bool b) {
    if (viewMode != ViewTable) {
        invertColormap = b;
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setInvertColormap(b);
        }
    }
}

void QFitsMultiBuffer::setFlipX(bool b) {
    if (viewMode != ViewTable) {
        flipX = b;
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setFlipX(b);
        }
    }
}

void QFitsMultiBuffer::setFlipY(bool b) {
    if (viewMode != ViewTable) {
        flipY = b;
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setFlipY(b);
        }
    }
}

void QFitsMultiBuffer::setBrightness(int b, bool sbInitialized) {
    if (viewMode != ViewTable) {
        if (b != brightness) {
            brightness = b;
            for (int i = 0; i < bufferList.size(); i++) {
                bufferList.at(i)->setBrightness(b, sbInitialized);
            }

            emit(newBrightness(b));
            setupColours();
        }
    }
}

void QFitsMultiBuffer::setContrast(int c, bool sbInitialized) {
    if (viewMode != ViewTable) {
        if (c != contrast) {
            contrast = c;
            for (int i = 0; i < bufferList.size(); i++) {
                bufferList.at(i)->setContrast(c, sbInitialized);
            }

            emit(newContrast(c));
            setupColours();
        }
    }
}

void QFitsMultiBuffer::setBrightnessContrast(int b, int c, bool sbInitialized) {
    if (viewMode != ViewTable) {
        if ((b != brightness) || (c != contrast)) {
            brightness = b;
            contrast = c;
            for (int i = 0; i < bufferList.size(); i++) {
                bufferList.at(i)->setBrightnessContrast(b, c, sbInitialized);
            }

            emit(newBrightness(b));
            emit(newContrast(c));
            setupColours();
        }
    }
}

void QFitsMultiBuffer::setImageScalingMethod(int s, bool sbInitialized) {
    if (viewMode != ViewTable) {
        if (s != imageScaleMethod) {
            imageScaleMethod = s;
            for (int i = 0; i < bufferList.size(); i++) {
                bufferList.at(i)->setImageScalingMethod(s, sbInitialized);
            }
        }
    }
}

void QFitsMultiBuffer::setRotation(int r) {
    if (viewMode != ViewTable) {
        rotation = r;
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setRotation(r);
        }
    }
}

void QFitsMultiBuffer::updateCubeMode() {
    if (viewMode != ViewTable) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->updateCubeMode();
        }
    }
}

QFitsSingleBuffer* QFitsMultiBuffer::getFirstImageBuffer() {
    QFitsSingleBuffer *sb = NULL;
    for (int i = 0; i < bufferList.size(); i++) {
        sb = bufferList.at(i)->getFirstImageBuffer();
        if (sb != NULL) {
            break;
        }
    }
    return sb;
}

bool QFitsMultiBuffer::showSpectrum() {
    if (hasCube ||
        ((getState() != NULL) && (mtv_tableMulti->getTableView()->doPlotData())))
    {
        return true;
    } else {
        return false;
    }
}

void QFitsMultiBuffer::createManualSpectrum() {
    for (int i = 0; i < bufferList.size(); i++) {
        bufferList.at(i)->createManualSpectrum();
    }
}

// this is only needed for the bloody QFitsTableModelMulti/GRAVITY/FITS-recursion
QFitsSingleBuffer* QFitsMultiBuffer::getSB(int index) {
    QFitsBaseBuffer *bb = bufferList.at(index);
    QFitsSingleBuffer *sb = dynamic_cast<QFitsSingleBuffer*>(bb);
    if (sb != NULL) {
        return sb;
    } else {
        return NULL;
    }
}

QFitsBaseWidget* QFitsMultiBuffer::getState() {
    if ((viewMode == ViewTable) && !hasChildMB) {
        return mtv_tableMulti;
    } else {
        return NULL;
    }
}

QFitsBaseWidget* QFitsMultiBuffer::getTableWidget() {
    return mtv_tableMulti;
}

void QFitsMultiBuffer::enableMovie(bool b) {
// AA: Hilfe! alle abspielen?!?
    if (viewMode != ViewTable) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->enableMovie(b);
        }
    }
}

void QFitsMultiBuffer::setXRange() {
    if (viewMode != ViewTable) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setXRange();
        }
    }
}

void QFitsMultiBuffer::setYRange() {
    if (viewMode != ViewTable) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setYRange();
        }
    }
}

void QFitsMultiBuffer::setYRange(const double &min, const double &max) {
    if (viewMode != ViewTable) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setYRange(min, max);
        }
    }
}

void QFitsMultiBuffer::setData() {
    if (viewMode != ViewTable) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setData();
        }
    }
}

void QFitsMultiBuffer::newData3D() {
    if (viewMode != ViewTable) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->newData3D();
        }
    }
}

void QFitsMultiBuffer::setMovieSpeed(int j) {
    if (viewMode != ViewTable) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setMovieSpeed(j);
        }
    }
}

void QFitsMultiBuffer::setImageCenter(double x, double y) {
    if (viewMode != ViewTable) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setImageCenter(x, y);
        }
    }
}

void QFitsMultiBuffer::setIgnore(bool isChecked, double val) {
    if (viewMode != ViewTable) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->setIgnore(isChecked, val);
        }
    }
}

void QFitsMultiBuffer::copyImage(int mode) {
// AA: to enhance!!!
    if (viewMode != ViewTable) {
        for (int i = 0; i < bufferList.size(); i++) {
            bufferList.at(i)->copyImage(mode);
        }
    } else {
        getTableWidget()->copyImage(mode);
    }
}
