/*  This file is part of KDevelop
    Copyright 2012 Miha Čančula <miha@noughmad.eu>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "templateoptionspage.h"
#include "templateclassassistant.h"
#include "debug.h"

#include <language/codegen/templateclassgenerator.h>
#include <language/codegen/sourcefiletemplate.h>

#include <QLineEdit>
#include <QSpinBox>
#include <QDomElement>
#include <QGroupBox>
#include <QVBoxLayout>
#include <QFormLayout>
#include <QLabel>
#include <QCheckBox>

using namespace KDevelop;

class KDevelop::TemplateOptionsPagePrivate
{
public:
    QList<SourceFileTemplate::ConfigOption> entries;
    QHash<QString, QWidget*> controls;
    QHash<QString, QByteArray> typeProperties;
    QList<QWidget*> groupBoxes;
};

TemplateOptionsPage::TemplateOptionsPage(QWidget* parent, Qt::WindowFlags f)
: QWidget(parent, f)
, d(new TemplateOptionsPagePrivate)
{
    d->typeProperties.insert(QStringLiteral("String"), "text");
    d->typeProperties.insert(QStringLiteral("Int"), "value");
    d->typeProperties.insert(QStringLiteral("Bool"), "checked");
}

TemplateOptionsPage::~TemplateOptionsPage()
{
    delete d;
}

void TemplateOptionsPage::load(const SourceFileTemplate& fileTemplate, TemplateRenderer* renderer)
{
    // TODO: keep any old changed values, as it comes by surprise to have them lost
    // when going back and forward

    // clear anything as there is on reentering the page
    d->entries.clear();
    d->controls.clear();
    // clear any old option group boxes & the base layout
    qDeleteAll(d->groupBoxes);
    d->groupBoxes.clear();
    delete layout();

    QVBoxLayout* layout = new QVBoxLayout();
    QHash<QString, QList<SourceFileTemplate::ConfigOption> > options = fileTemplate.customOptions(renderer);
    QHash<QString, QList<SourceFileTemplate::ConfigOption> >::const_iterator it;

    for (it = options.constBegin(); it != options.constEnd(); ++it)
    {
        QGroupBox* box = new QGroupBox(this);
        d->groupBoxes.append(box);

        box->setTitle(it.key());

        QFormLayout* formLayout = new QFormLayout;

        d->entries << it.value();
        foreach (const SourceFileTemplate::ConfigOption& entry, it.value())
        {
            QWidget* control = nullptr;
            const QString type = entry.type;
            if (type == QLatin1String("String"))
            {
                control = new QLineEdit(entry.value.toString(), box);
            }
            else if (type == QLatin1String("Int"))
            {
                auto input = new QSpinBox(box);
                input->setValue(entry.value.toInt());
                if (!entry.minValue.isEmpty())
                {
                    input->setMinimum(entry.minValue.toInt());
                }
                if (!entry.maxValue.isEmpty())
                {
                    input->setMaximum(entry.maxValue.toInt());
                }
                control = input;
            }
            else if (type == QLatin1String("Bool"))
            {
                bool checked = (QString::compare(entry.value.toString(), QStringLiteral("true"), Qt::CaseInsensitive) == 0);
                QCheckBox* checkBox = new QCheckBox(box);
                checkBox->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
                control = checkBox;
            }
            else
            {
                qCDebug(PLUGIN_FILETEMPLATES) << "Unrecognized option type" << entry.type;
            }
            if (control)
            {
                QLabel* label = new QLabel(entry.label, box);
                formLayout->addRow(label, control);
                d->controls.insert(entry.name, control);
            }
        }

        box->setLayout(formLayout);
        layout->addWidget(box);
    }

    layout->addStretch();

    setLayout(layout);
}

QVariantHash TemplateOptionsPage::templateOptions() const
{
    QVariantHash values;

    foreach (const SourceFileTemplate::ConfigOption& entry, d->entries)
    {
        Q_ASSERT(d->controls.contains(entry.name));
        Q_ASSERT(d->typeProperties.contains(entry.type));

        values.insert(entry.name, d->controls[entry.name]->property(d->typeProperties[entry.type]));
    }

    qCDebug(PLUGIN_FILETEMPLATES) << values.size() << d->entries.size();

    return values;
}
