/*****************************************************************************
 * $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 "TextViewer.h"

// -- Core stuff
#include <Application.h>
#include <SettingsDialog.h>
#include <MainWindow.h>

//-- Qt stuff
#include <QHBoxLayout>

using namespace camitk;

// -------------------- Constructor --------------------
TextViewer::TextViewer(QString name) : Viewer(name, Viewer::DOCKED) {
    inverse = nullptr;
    myMenu = nullptr;
    myWidget = nullptr;
    displayedTopLevelComponents = 0;
    setIcon(QPixmap(":/textviewer"));
    setDescription("This text only viewer displays the number of opened components (docked by default)");

    propertyObject = new PropertyObject(getName());
    Property* property = new Property("Background Color", QColor(Qt::white), "Text background color, modifiable in the TextViewer settings", "");
    propertyObject->addProperty(property);

    property = new Property("Text Color", QColor(Qt::blue), "Text color, modifiable in the TextViewer settings", "");
    propertyObject->addProperty(property);

    // propertyObject is monitored by the TextViewer instance (this) when its properties change
    propertyObject->installEventFilter(this);
}

// -------------------- Destructor --------------------
TextViewer::~TextViewer() {
    delete myWidget;
    delete propertyObject;
}

// -------------------- refresh --------------------
void TextViewer::refresh(Viewer*) {
    // view everything?
    if (displayedTopLevelComponents != (unsigned) Application::getTopLevelComponents().size()) {
        // if there the nr of Component changed since last refresh,
        // to something!
        output->append("There was " + QString::number(displayedTopLevelComponents) + " top-level components");
        output->append("Now there is " + QString::number(Application::getTopLevelComponents().size()));
        output->append("(" + QString::number(Application::getAllComponents().size()) + " components in total)");
        output->append("");

        // update the counter
        displayedTopLevelComponents = Application::getTopLevelComponents().size();
    }
}

// -------------------- getWidget --------------------
QWidget* TextViewer::getWidget() {
    if (myWidget == nullptr) {
        myWidget = new QWidget();
        output = new QTextEdit();
        //-- init layout
        auto* myWidgetLayout = new QHBoxLayout();
        myWidgetLayout->setSpacing(0);
        myWidgetLayout->setContentsMargins(0, 0, 0, 0);

        //-- add the output text edit
        myWidgetLayout->addWidget(output);

        myWidget->setLayout(myWidgetLayout);
        updateColors();
    }

    return myWidget;
}

// ---------------------- getPropertyObject ----------------------------
PropertyObject* TextViewer::getPropertyObject() {
    //  (change the text/background color)
    return propertyObject;
}

// -------------------- getMenu --------------------
QMenu* TextViewer::getMenu() {
    if (!myMenu) {
        //-- create the main menu
        myMenu = new QMenu(objectName());

        //-- add the action
        inverse = new QAction(tr("&Invert Display"), this);
        inverse->setCheckable(true);

        connect(inverse, SIGNAL(triggered(bool)), this, SLOT(invertColors(bool)));

        myMenu->addAction(inverse);
    }
    return myMenu;
}

// -------------------- invertColors --------------------
void TextViewer::invertColors(bool isInverted) {
    QColor oldBackgroundColor = propertyObject->property("Background Color").value<QColor>();
    QColor oldTextColor = propertyObject->property("Text Color").value<QColor>();

    propertyObject->setProperty("Background Color", oldTextColor);
    propertyObject->setProperty("Text Color", oldBackgroundColor);

    updateColors();

    output->append((isInverted) ? "Inverted colors" : "Normal colors");
}

// -------------------- updateColors --------------------
void TextViewer::updateColors() {
    output->setTextColor(propertyObject->property("Text Color").value<QColor>());
    output->setTextBackgroundColor(propertyObject->property("Background Color").value<QColor>());
    output->append("Colors updated");
}

// ---------------- eventFilter ----------------
bool TextViewer::eventFilter(QObject* object, QEvent* event) {
    // watch propertyObject instance for dynamic property changes
    if (event->type() == QEvent::DynamicPropertyChange) {
        updateColors();
        return true;
    }
    else {
        // pass the event on to the parent class
        return Viewer::eventFilter(object, event);
    }

}

// -------------------- editPreference --------------------
void TextViewer::editPreference() {
    SettingsDialog settingsDialog;
    settingsDialog.editSettings(propertyObject);
    settingsDialog.exec();
    updateColors();
}