/**
 * SPDX-FileCopyrightText: 1999-2001 Lubos Lunak <l.lunak@kde.org>
 * SPDX-FileCopyrightText: 2009 Michael Jansen <kde@michael-jansen.biz>
 *
 * SPDX-License-Identifier: LGPL-2.0-or-later
 **/

#include "settings_writer.h"

#include "action_data/action_data.h"
#include "action_data/action_data_group.h"
#include "action_data/generic_action_data.h"
#include "action_data/menuentry_shortcut_action_data.h"
#include "action_data/simple_action_data.h"

#include "conditions/conditions_list.h"

#include "windows_helper/window_selection_list.h"

#include <KConfig>
#include <KConfigGroup>
#include <QDebug>

namespace KHotKeys
{
const int CurrentFileVersion = 2;

SettingsWriter::SettingsWriter(const Settings *settings, ActionState state, const QString &id, bool allowMerging)
    : _settings(settings)
    , _state(state)
    , _importId(id)
    , _allowMerging(allowMerging)
    , _export(false)
{
}

void SettingsWriter::exportTo(const ActionDataBase *element, KConfigBase &config)
{
    _export = true;

    if (!element) {
        Q_ASSERT(element);
        return;
    }

    // Clean the file
    QStringList groups = config.groupList();
    Q_FOREACH (const QString &name, config.groupList()) {
        config.deleteGroup(name);
    }

    KConfigGroup mainGroup(&config, "Main");
    mainGroup.writeEntry("Version", CurrentFileVersion);
    mainGroup.writeEntry("AllowMerge", _allowMerging);

    if (!_importId.isEmpty())
        mainGroup.writeEntry("ImportId", _importId);

    // The root group contains nothing but the datacount!
    KConfigGroup dataGroup(&config, "Data");
    dataGroup.writeEntry("DataCount", 1);

    // The group for the element to export
    KConfigGroup data1Group(&config, "Data_1");
    _stack.push(&data1Group);
    element->accept(this);
    _stack.pop();

    _export = false;
}

void SettingsWriter::visitActionData(const ActionData *data)
{
    visitActionDataBase(data);

    KConfigGroup *config = _stack.top();

    // Write triggers if available
    if (data->triggers()) {
        KConfigGroup triggersGroup(config->config(), config->name() + "Triggers");
        data->triggers()->cfg_write(triggersGroup);
    }

    // Write actions if available
    if (data->actions()) {
        KConfigGroup actionsGroup(config->config(), config->name() + "Actions");
        data->actions()->cfg_write(actionsGroup);
    }
}

void SettingsWriter::visitActionDataBase(const ActionDataBase *base)
{
    KConfigGroup *config = _stack.top();

    config->writeEntry("Type", "ERROR"); // derived classes should call with their type
    config->writeEntry("Name", base->name());
    config->writeEntry("Comment", base->comment());

    switch (_state) {
    case KHotKeys::Retain:
        config->writeEntry("Enabled", base->isEnabled(ActionDataBase::Ignore));
        break;

    case KHotKeys::Enabled:
        config->writeEntry("Enabled", true);
        break;

    case KHotKeys::Disabled:
        config->writeEntry("Enabled", false);
        break;

    default:
        Q_ASSERT(false);
        config->writeEntry("Enabled", false);
    }

    if (base->conditions()) {
        KConfigGroup conditionsConfig(config->config(), config->name() + "Conditions");
        base->conditions()->cfg_write(conditionsConfig);
    } else {
        qDebug() << "No conditions";
    }
}

void SettingsWriter::visitActionDataGroup(const ActionDataGroup *group)
{
    visitActionDataBase(group);

    KConfigGroup *config = _stack.top();

    config->writeEntry("SystemGroup", int(group->system_group()));
    config->writeEntry("Type", "ACTION_DATA_GROUP");

    int cnt = 0;
    Q_FOREACH (ActionDataBase *child, group->children()) {
        ++cnt;
        KConfigGroup childConfig(config->config(), config->name() + QString("_") + QString::number(cnt));
        _stack.push(&childConfig);
        child->accept(this);
        _stack.pop();
    }
    config->writeEntry("DataCount", cnt);

    // We only write those two back if we do not export the settings
    if (!_export) {
        // ImportId only if set
        if (!group->importId().isEmpty())
            config->writeEntry("ImportId", group->importId());
        if (group->allowMerging())
            config->writeEntry("AllowMerge", group->allowMerging());
    }
}

void SettingsWriter::visitGenericActionData(const Generic_action_data *data)
{
    visitActionData(data);

    KConfigGroup *config = _stack.top();
    config->writeEntry("Type", "GENERIC_ACTION_DATA");
}

void SettingsWriter::visitMenuentryShortcutActionData(const MenuEntryShortcutActionData *data)
{
    visitActionData(data);

    KConfigGroup *config = _stack.top();
    config->writeEntry("Type", "MENUENTRY_SHORTCUT_ACTION_DATA");
}

void SettingsWriter::visitSimpleActionData(const SimpleActionData *data)
{
    visitActionData(data);

    KConfigGroup *config = _stack.top();
    config->writeEntry("Type", "SIMPLE_ACTION_DATA");
}

void SettingsWriter::writeTo(KConfigBase &config)
{
    QStringList groups = config.groupList();
    for (QStringList::ConstIterator it = groups.constBegin(); it != groups.constEnd(); ++it)
        config.deleteGroup(*it);

    // Write the global settings
    KConfigGroup mainGroup(&config, "Main");
    mainGroup.writeEntry("Version", 2);
    mainGroup.writeEntry("AlreadyImported", _settings->already_imported);
    mainGroup.writeEntry("Disabled", _settings->isDaemonDisabled());

    // Write the actions
    KConfigGroup dataGroup(&config, "Data");
    _stack.push(&dataGroup);

    int cnt = 0;
    if (_settings->actions()) {
        Q_FOREACH (ActionDataBase *child, _settings->actions()->children()) {
            ++cnt;
            KConfigGroup childConfig(dataGroup.config(), QString("Data_") + QString::number(cnt));
            _stack.push(&childConfig);
            child->accept(this);
            _stack.pop();
        }
    }
    dataGroup.writeEntry("DataCount", cnt);
    _stack.pop();

    // CHECKME Count still needed????
    // int cnt = write_actions( dataGroup, _settings->actions(), true );
    // mainGroup.writeEntry( "Autostart", cnt != 0 && !_settings->isDaemonDisabled() );

    // Write the gestures configuration
    KConfigGroup gesturesConfig(&config, "Gestures");
    gesturesConfig.writeEntry("Disabled", _settings->areGesturesDisabled());
    gesturesConfig.writeEntry("MouseButton", _settings->gestureMouseButton());
    gesturesConfig.writeEntry("Timeout", _settings->gestureTimeOut());
    if (_settings->gesturesExclude() != nullptr) {
        KConfigGroup gesturesExcludeConfig(&config, "GesturesExclude");
        _settings->gesturesExclude()->cfg_write(gesturesExcludeConfig);
    } else
        config.deleteGroup("GesturesExclude");
    KConfigGroup voiceConfig(&config, "Voice");
    voiceConfig.writeEntry("Shortcut", _settings->voice_shortcut.toString());
}

} // namespace KHotKeys
