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

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

#include "LineFactory.h"
#include "MvIconParameter.h"
#include "MvQTheme.h"
#include "RequestPanel.h"
#include "MvLog.h"
#include "MvMiscellaneous.h"

#include <QDebug>

MvQTextLine::MvQTextLine(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()));
}

void MvQTextLine::refresh(const std::vector<std::string>& values)
{
    std::string s;
    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
            //  "something" + "."  or
            //  "-"
            // we do not 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();
                }
            }
        }
    }

    checkValidity();
}

void MvQTextLine::dispatchChange()
{
    std::vector<std::string> vals;
    QString txt = lineEdit_->text();
    foreach (QString s, txt.split("/")) {
        vals.push_back(s.toStdString());
    }

    owner_.set(param_.name(), vals);

    checkValidity();
}

void MvQTextLine::updateHelper()
{
    if (doNotUpdateHelper_ || !helper_)
        return;

    std::vector<std::string> vals;
    QString txt = lineEdit_->text();
    foreach (QString s, txt.split("/")) {
        vals.push_back(s.toStdString());
        helper_->refresh(vals);
    }
    helper_->refresh(vals);
}

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

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

void MvQTextLine::slotHelperEdited(QStringList vals, QVector<bool> st)
{
    QString txt = lineEdit_->text();
    QStringList lst = txt.split("/");

    for (int i = 0; i < vals.size(); i++) {
        if (st[i] && !lst.contains(vals[i])) {
            lst << vals[i];
        }
        else if (!st[i] && lst.contains(vals[i])) {
            lst.removeAll(vals[i]);
        }
    }

    //    for (std::vector<std::string>::const_iterator it = values.begin(); it != values.end(); it++) {
    //        QString s(it->c_str());
    //        if (!lst.contains(s))
    //            lst << s;
    //    }

    //    for (std::vector<std::string>::const_iterator it = noValues.begin(); it != noValues.end(); it++) {
    //        QString s(it->c_str());
    //        if (lst.contains(s))
    //            lst.removeAll(s);
    //    }

    QString res = lst.join("/");
    if (res.startsWith("/"))
        res.remove(0, 1);

    if (res != txt) {
        doNotUpdateHelper_ = true;
        lineEdit_->setText(res);
        dispatchChange();
        doNotUpdateHelper_ = false;
    }
}

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

void MvQTextLine::checkValidity()
{
    // Check if commma separator is used instead of forward slash

    // Only performs the check if LC_NUMERIC=C to make sure dot is used for decimal
    // place in numbers.
    if (!metview::is_locale_numeric_set()) {
        return;
    }

    auto t = lineEdit_->text();

    // An extremely simple assumption to check if the correct separator is used.
    // Will not work for strings containing commas.
    bool wrong = t.contains(",") && !t.contains("/");

    if (wrong) {
        if (!warningLabelStatus()) {
            static QString warnMsg = "In icon editors a <b>forward slash</b> ('/') must be used as "
                                     "<b>list separator</b>. It seems comma (',') is used instead!";
            setWarningLabelStatus(true, warnMsg);
            auto sh = MvQTheme::styleSheet("lineedit", "warning_sh");
            lineEdit_->setStyleSheet(sh);
            lineEdit_->setToolTip(warnMsg);
        }
    } else if (warningLabelStatus()) {
        setWarningLabelStatus(false);
        lineEdit_->setStyleSheet("");
        lineEdit_->setToolTip("");

    }
}

static LineMaker<MvQTextLine> maker1("text");
