/*
 *  Copyright (C) 2010 Andriy Rysin (rysin@kde.org)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "keyboard_config.h"
#include "debug.h"

#include <ksharedconfig.h>
#include <kconfiggroup.h>


static const char* const SWITCHING_POLICIES[] = {"Global", "Desktop", "WinClass", "Window", nullptr };
static const char LIST_SEPARATOR[] = ",";
//static const char* DEFAULT_LAYOUT = "us";
static const char DEFAULT_MODEL[] = "pc104";

static const QString CONFIG_FILENAME(QStringLiteral("kxkbrc"));
static const QString CONFIG_GROUPNAME(QStringLiteral("Layout"));

const int KeyboardConfig::NO_LOOPING = -1;

KeyboardConfig::KeyboardConfig()
{
    setDefaults();
}

QString KeyboardConfig::getSwitchingPolicyString(SwitchingPolicy switchingPolicy) {
    return SWITCHING_POLICIES[switchingPolicy];
}

static int findStringIndex(const char* const strings[], const QString& toFind, int defaultIndex)
{
    for(int i=0; strings[i] != nullptr; i++) {
        if( toFind == strings[i] ) {
            return i;
        }
    }
    return defaultIndex;
}

void KeyboardConfig::setDefaults()
{
    keyboardModel = DEFAULT_MODEL;
    resetOldXkbOptions = false;
    xkbOptions.clear();

    // init layouts options
    configureLayouts = false;
    layouts.clear();
//	layouts.append(LayoutUnit(DEFAULT_LAYOUT));
    layoutLoopCount = NO_LOOPING;

    // switch control options
    switchingPolicy = SWITCH_POLICY_GLOBAL;
//	stickySwitching = false;
//	stickySwitchingDepth = 2;

    // display options
    showIndicator = true;
    indicatorType = SHOW_LABEL;
    showSingle = false;
}

static
KeyboardConfig::IndicatorType getIndicatorType(bool showFlag, bool showLabel)
{
    if( showFlag ) {
        if( showLabel )
            return KeyboardConfig::SHOW_LABEL_ON_FLAG;
        else
            return KeyboardConfig::SHOW_FLAG;
    }
    else {
        return KeyboardConfig::SHOW_LABEL;
    }
}


void KeyboardConfig::load()
{
    KConfigGroup config(KSharedConfig::openConfig( CONFIG_FILENAME, KConfig::NoGlobals ), CONFIG_GROUPNAME);

    keyboardModel = config.readEntry("Model", "");

    resetOldXkbOptions = config.readEntry("ResetOldOptions", false);
    QString options = config.readEntry("Options", "");
    xkbOptions = options.split(LIST_SEPARATOR, QString::SkipEmptyParts);

    configureLayouts = config.readEntry("Use", false);
    QString layoutsString = config.readEntry("LayoutList", "");
    QStringList layoutStrings = layoutsString.split(LIST_SEPARATOR, QString::SkipEmptyParts);
//    if( layoutStrings.isEmpty() ) {
//    	layoutStrings.append(DEFAULT_LAYOUT);
//    }
    layouts.clear();
    foreach(const QString& layoutString, layoutStrings) {
        layouts.append(LayoutUnit(layoutString));
    }
    if( layouts.isEmpty() ) {
        configureLayouts = false;
    }

    layoutLoopCount = config.readEntry("LayoutLoopCount", NO_LOOPING);

    QString layoutMode = config.readEntry("SwitchMode", "Global");
    switchingPolicy = static_cast<SwitchingPolicy>(findStringIndex(SWITCHING_POLICIES, layoutMode, SWITCH_POLICY_GLOBAL));

    showIndicator = config.readEntry("ShowLayoutIndicator", true);

    bool showFlag = config.readEntry("ShowFlag", false);
    bool showLabel = config.readEntry("ShowLabel", true);
    indicatorType = getIndicatorType(showFlag, showLabel);

    showSingle = config.readEntry("ShowSingle", false);

    QString labelsStr = config.readEntry("DisplayNames", "");
    QStringList labels = labelsStr.split(LIST_SEPARATOR, QString::KeepEmptyParts);
    for(int i=0; i<labels.count() && i<layouts.count(); i++) {
        if( !labels[i].isEmpty() && labels[i] != layouts[i].layout ) {
            layouts[i].setDisplayName(labels[i]);
        }
    }

//    QString shortcutsStr = config.readEntry("LayoutShortcuts", "");
//    QStringList shortcutsList = shortcutsStr.split(LIST_SEPARATOR, QString::KeepEmptyParts);
//    for(int i=0; i<shortcutsList.count() && i<layouts.count(); i++) {
//    	if( !shortcutsList[i].isEmpty() ) {
//    		layouts[i].setShortcut(QKeySequence(shortcutsList[i]));
//    	}
//    }

    qCDebug(KCM_KEYBOARD) << "configuring layouts" << configureLayouts << "configuring options" << resetOldXkbOptions;
}

void KeyboardConfig::save()
{
    KConfigGroup config(KSharedConfig::openConfig( CONFIG_FILENAME, KConfig::NoGlobals ), CONFIG_GROUPNAME);

    config.writeEntry("Model", keyboardModel);

    config.writeEntry("ResetOldOptions", resetOldXkbOptions);
    if( resetOldXkbOptions ) {
        config.writeEntry("Options", xkbOptions.join(LIST_SEPARATOR));
    }
    else {
        config.deleteEntry("Options");
    }

    config.writeEntry("Use", configureLayouts);

    QStringList layoutStrings;
    QStringList displayNames;
//    QStringList shortcuts;
    foreach(const LayoutUnit& layoutUnit, layouts) {
        layoutStrings.append(layoutUnit.toString());
        displayNames.append(layoutUnit.getRawDisplayName());
//    	shortcuts.append(layoutUnit.getShortcut().toString());
    }
    config.writeEntry("LayoutList", layoutStrings.join(LIST_SEPARATOR));
    config.writeEntry("DisplayNames", displayNames.join(LIST_SEPARATOR));
//    config.writeEntry("LayoutShortcuts", shortcuts.join(LIST_SEPARATOR));

    config.writeEntry("LayoutLoopCount", layoutLoopCount);

    config.writeEntry("SwitchMode", SWITCHING_POLICIES[switchingPolicy]);

    config.writeEntry("ShowLayoutIndicator", showIndicator);
    config.writeEntry("ShowFlag", indicatorType == SHOW_FLAG || indicatorType == SHOW_LABEL_ON_FLAG);
    config.writeEntry("ShowLabel", indicatorType == SHOW_LABEL || indicatorType == SHOW_LABEL_ON_FLAG);
    config.writeEntry("ShowSingle", showSingle);

    config.sync();
}

QList<LayoutUnit> KeyboardConfig::getDefaultLayouts() const
{
    QList<LayoutUnit> defaultLayoutList;
    int i = 0;
    foreach(const LayoutUnit& layoutUnit, layouts) {
        defaultLayoutList.append(layoutUnit);
        if( layoutLoopCount != KeyboardConfig::NO_LOOPING && i >= layoutLoopCount-1 )
            break;
        i++;
    }
    return defaultLayoutList;
}

QList<LayoutUnit> KeyboardConfig::getExtraLayouts() const
{
    if( layoutLoopCount == KeyboardConfig::NO_LOOPING )
        return QList<LayoutUnit>();

    return layouts.mid(layoutLoopCount, layouts.size());
}
