/***************************** LICENSE START ***********************************

 Copyright 2015 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include "MvQStringLine.h"

#include "MvQRequestPanelHelp.h"
#include "MvQLineEdit.h"

#include "LineFactory.h"
#include "MvIconParameter.h"
#include "RequestPanel.h"

#include <QDebug>


MvQStringLine::MvQStringLine(RequestPanel& owner, const MvIconParameter& param) :
    MvQRequestPanelLine(owner, param)
{
    lineEdit_ = new MvQLineEdit(parentWidget_);

    owner_.addWidget(lineEdit_, row_, WidgetColumn);

    connect(lineEdit_, SIGNAL(textEdited(const QString&)),
            this, SLOT(slotTextEdited(const QString&)));

    connect(lineEdit_, SIGNAL(textCleared()),
            this, SLOT(slotCleared()));
}

//It is called when the value was updated in the request and we
//need to display the new string.

void MvQStringLine::refresh(const std::vector<std::string>& values)
{
    std::string s;

    //Create a metview list form the vector of strings
    for (const auto& value : values) {
        if (s.length())
            s += "/";
        s += value;
    }

    //Now this is the tricky part. Whenever the user types in a new character the
    //lineedit emits a changed signal and the request gets updated. And in the end this (refresh())
    //function will be called with the new text. Ideally the new string and the string stored in
    //the lineedit should be the same. However, mars tends to change incomplete floating point numbers like
    // "7." into integers!! So when the user wants to change e.g. "7.1" to "7.3" when they reach "7."
    //during the editing the string changes back to "7". In this case we do not want to set the linedit.
    //So we need to carefully compare the new and the previous string and decide what to do.

    std::string prevText = lineEdit_->text().toStdString();

    if (s.empty() || s != prevText) {
        //Single strings
        if (values.size() <= 1) {
            //if the original string was not
            // "something" + "." we update the lineedit
            if ((s + "." == prevText) ||
                (prevText == "-" && !s.empty() && s[0] == '-')) {
                return;
            }

            lineEdit_->setText(s.c_str());
            updateHelper();
        }
        //Lists
        else {
            QStringList lst     = QString::fromStdString(s).split("/");
            QStringList prevLst = QString::fromStdString(prevText).split("/");

            if (lst.count() == prevLst.count()) {
                bool found = false;
                for (int i = 0; i < lst.count(); i++) {
                    if ((lst[i] + "." == prevLst[i]) ||
                        (prevLst[i] == "-" && !lst[i].isEmpty() && lst.at(i).at(0) == '-')) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    lineEdit_->setText(s.c_str());
                    updateHelper();
                }
            }
            else {
                if ('/' + s != prevText) {
                    lineEdit_->setText(s.c_str());
                    updateHelper();
                }
            }
        }
    }
}

void MvQStringLine::dispatchChange()
{
    owner_.set(param_.name(), lineEdit_->text().toStdString());
}

void MvQStringLine::updateHelper()
{
    if (!helper_)
        return;

    std::vector<std::string> vals;
    vals.push_back(lineEdit_->text().toStdString());
    helper_->refresh(vals);
}

void MvQStringLine::slotCleared()
{
    dispatchChange();
    updateHelper();
}

void MvQStringLine::slotTextEdited(const QString& /*text*/)
{
    dispatchChange();
    updateHelper();
}

void MvQStringLine::slotHelperEdited(const std::vector<std::string>& values)
{
    if (values.size() > 0) {
        QString s(values[0].c_str());
        lineEdit_->setText(s);
        dispatchChange();
    }
}

static LineMaker<MvQStringLine> maker1("string");
