/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
 *
 * Visit http://camitk.imag.fr for more information
 *
 * This file is part of CamiTK.
 *
 * CamiTK is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * CamiTK 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 Lesser General Public License version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with CamiTK.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $CAMITK_LICENCE_END$
 ****************************************************************************/

#include <pml/PhysicalModel.h>
#include <pml/Atom.h>

#include <monitoringgui/MonitoringGuiManager.h>
#include <monitoringgui/MonitoringDialog.h>
//#include <monitor/monitors/MonitorPosition.h>


#include "MMLDisplay.h"
#include "MMLComponent.h"
#include "MMLMonitorDisplay.h"

#include <PMLComponent.h>

#include <QtGui>
#include <QTableWidget>
#include <QRadioButton>
#include <QComboBox>

#include "MMLMonitorDisplayFactory.h"
#include <MonitoringDriver.h>
#include <vtkPointData.h>

MMLDisplay::MMLDisplay(MMLComponent* mmlManager): QObject() {
    this->mmlManager = mmlManager;
    auto* qobj = (QObject*)(mmlManager->getMonitoringGuiManager());
    QObject* qobj2 = (QObject*)(mmlManager->getMonitoringGuiManager()->getDialog());
    connect(qobj, SIGNAL(changed()), this, SLOT(updateDisplay()));
    connect(qobj2, SIGNAL(monitorsChanged()), this, SLOT(updateMonitorsTable()));
    connect(qobj, SIGNAL(reconnectPml()), this, SLOT(connectPml()));
    monitorDisplay = nullptr;

    // add two column in monitors table for displaying monitors
    QTableWidget* table = mmlManager->getMonitoringGuiManager()->getDialog()->getMonitorsTableWidget();
    int i = table->columnCount();
    table->setColumnCount(i + 2);
    auto* item1 = new QTableWidgetItem();
    item1->setText(tr("Display"));
    table->setHorizontalHeaderItem(i, item1);
    auto* item2 = new QTableWidgetItem();
    item2->setText(tr("Display Type"));
    table->setHorizontalHeaderItem(i + 1, item2);
}

MMLDisplay::~MMLDisplay() {
    if (monitorDisplay) {
        delete monitorDisplay;
    }
}


// ---------------------- updateDisplay ----------------------------
void MMLDisplay::updateDisplay() {
    // Update monitor display
    if (monitorDisplay) {
        monitorDisplay->update();
    }

    // TODO update this code for pmlcomponent (no more AtomDC)
    // There might be nothing to do but delete this commented code!
    /*
    // update loads and atom data if any (override monitors)
    pmMgr->getLoadsManager()->getLoadsSimulation()->updateAtomData();
    pmMgr->getLoadsManager()->updateLoadsDisplay();
    */

    // updating atom's position in 3D is automatic (pml and vtk memory are shared), just update the display
    mmlManager->getPMLComponent()->refreshDisplay();

}

// ---------------------- connectMonitor ----------------------------
void MMLDisplay::connectMonitor() {

    Monitor* m = nullptr;
    std::string s = "";

    QTableWidget* table = mmlManager->getMonitoringGuiManager()->getDialog()->getMonitorsTableWidget();

    for (int i = 0; i < table->rowCount(); i++) {
        auto* qrb = (QRadioButton*)(table->cellWidget(i, 5));
        if (qrb->isChecked()) {
            m = mmlManager->getMonitoringGuiManager()->getMonitoringManager()->getMonitor(i);
            QComboBox* qcb = (QComboBox*)(table->cellWidget(i, 6));
            s = qcb->currentText().toStdString();
        }
    }

    if (m) {
        if (monitorDisplay) {
            monitorDisplay->hide();
            delete monitorDisplay;
        }
        MMLMonitorDisplayFactory* fact = MMLMonitorDisplayFactory::getInstance();
        monitorDisplay = fact->createMonitorDisplay(s, m, mmlManager);
    }

    updateDisplay();
}

// ---------------------- updateMonitorsTable ----------------------------
void MMLDisplay::updateMonitorsTable() {
    QTableWidget* table = mmlManager->getMonitoringGuiManager()->getDialog()->getMonitorsTableWidget();

    for (int i = 0; i < table->rowCount(); i++) {
        auto* r = new QRadioButton();
        table->setCellWidget(i, 5, r);
        connect(r, SIGNAL(toggled(bool)), this, SLOT(connectMonitor()));

        // create a combo box to choose how to display monitor
        QComboBox* cbox = new QComboBox();
        Monitor* monitor = mmlManager->getMonitoringGuiManager()->getMonitoringManager()->getMonitor(i);
        MMLMonitorDisplayFactory* fact = MMLMonitorDisplayFactory::getInstance();
        for (unsigned int j = 0; j < fact->getNumberOfDisplaysByType(monitor->getValueType()); j++) {
            std::string s = fact->getDisplayByType(monitor->getValueType(), j);
            cbox->insertItem(j, s.c_str());
        }

        table->setCellWidget(i, 6, cbox);
        connect(cbox, SIGNAL(currentIndexChanged(int)), this, SLOT(connectMonitor()));
    }
}

// -------------------- refreshModified ---------------------
Monitor* MMLDisplay::getDisplayedMonitor() {
    QTableWidget* table = mmlManager->getMonitoringGuiManager()->getDialog()->getMonitorsTableWidget();

    for (int i = 0; i < table->rowCount(); i++) {
        auto* qrb = (QRadioButton*)(table->cellWidget(i, 5));
        if (qrb->isChecked()) {
            return mmlManager->getMonitoringGuiManager()->getMonitoringManager()->getMonitor(i);
        }
    }
    return nullptr;
}

// -------------------- getDisplayedMonitorLine ---------------------
int MMLDisplay::getDisplayedMonitorLine() {
    QTableWidget* table = mmlManager->getMonitoringGuiManager()->getDialog()->getMonitorsTableWidget();

    for (int i = 0; i < table->rowCount(); i++) {
        auto* qrb = (QRadioButton*)(table->cellWidget(i, 5));
        if (qrb->isChecked()) {
            return i;
        }
    }
    return -1;
}

// -------------------- connectPml ---------------------
void MMLDisplay::connectPml() {
    mmlManager->connectPml();
}
