/*****************************************************************************
 * $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$
 ****************************************************************************/

// -- Core stuff
#include "SliderSpinBoxWidget.h"

// -- QT stuff
#include <QVBoxLayout>
#include <QHBoxLayout>


namespace camitk {
//--------------------- constructor ------------------------
SliderSpinBoxWidget::SliderSpinBoxWidget(QWidget* parent) : QWidget(parent) {

    setObjectName("camitk::SliderSpinBoxWidget");

    //-- create UI
    auto* vLayout = new QVBoxLayout(this);
    vLayout->setSpacing(0);
    vLayout->setContentsMargins(0, 0, 0, 0);

    spinBox = new QSpinBox;
    QFont spinBoxFont = spinBox->font();
    spinBoxFont.setPointSize(10);
    spinBox->setFont(spinBoxFont);
    vLayout->addWidget(spinBox);

    auto* hLayout = new QHBoxLayout();
    vLayout->addLayout(hLayout);
    slider = new QSlider(Qt::Vertical);
    hLayout->addWidget(slider);

    //-- connect for synchronization
    connect(spinBox, SIGNAL(valueChanged(int)), SLOT(spinBoxValueChanged(int)));
    connect(slider, SIGNAL(valueChanged(int)), SLOT(sliderValueChanged(int)));
}

//--------------------- getValue ------------------------
int SliderSpinBoxWidget::getValue() const {
    return slider->value();
}

//--------------------- setValue ------------------------
void SliderSpinBoxWidget::setValue(int value) {
    if (getValue() != value) {
        updateSpinBoxValue(value);
        updateSliderValue(value);
    }
}

//--------------------- setRange ------------------------
void SliderSpinBoxWidget::setRange(int min, int max) {
    int pageStep = (max - min) / 10;

    if (pageStep < 1) {
        pageStep = 1;
    }

    slider->setRange(min, max);
    slider->setSingleStep(1);
    slider->setPageStep(pageStep);

    spinBox->setRange(min, max);
    spinBox->setSingleStep(1);
}

//--------------------- spinBoxValueChanged ------------------------
void SliderSpinBoxWidget::spinBoxValueChanged(int value) {
    updateSliderValue(value);
    emit valueChanged(value);
}

//--------------------- sliderValueChanged ------------------------
void SliderSpinBoxWidget::sliderValueChanged(int value) {
    updateSpinBoxValue(value);
    emit valueChanged(value);
}

//--------------------- updateSpinBoxValue ------------------------
void SliderSpinBoxWidget::updateSpinBoxValue(int value) {
    // -- set the spinBox value
    bool alreadyBlocked = spinBox->signalsBlocked();

    if (!alreadyBlocked) {
        spinBox->blockSignals(true);
    }

    spinBox->setValue(value);

    if (!alreadyBlocked) {
        spinBox->blockSignals(false);
    }
}

//--------------------- updateSliderValue ------------------------
void SliderSpinBoxWidget::updateSliderValue(int value) {
    // -- set the slider value
    bool alreadyBlocked = slider->signalsBlocked();

    if (!alreadyBlocked) {
        slider->blockSignals(true);
    }

    slider->setValue(value);

    if (!alreadyBlocked) {
        slider->blockSignals(false);
    }
}


//--------------------- addSingleStep ------------------------
void SliderSpinBoxWidget::addSingleStep() {
    if (slider->value() <= (slider->maximum() - slider->singleStep())) {
        setValue(slider->value() + slider->singleStep());
    }
    else {
        setValue(slider->maximum());
    }
}

//--------------------- subSingleStep ------------------------
void SliderSpinBoxWidget::subSingleStep() {
    if (slider->value() >= (slider->minimum() + slider->singleStep())) {
        setValue(slider->value() - slider->singleStep());
    }
    else {
        setValue(slider->minimum());
    }
}


//--------------------- addPageStep ------------------------
void SliderSpinBoxWidget::addPageStep() {
    if (slider->value() <= (slider->maximum() - slider->pageStep())) {
        setValue(slider->value() + slider->pageStep());
    }
    else {
        setValue(slider->maximum());
    }
}

//--------------------- subPageStep ------------------------
void SliderSpinBoxWidget::subPageStep() {
    if (slider->value() >= (slider->minimum() + slider->pageStep())) {
        setValue(slider->value() - slider->pageStep());
    }
    else {
        setValue(slider->minimum());
    }
}


}



