// Description: Advanced settings dialog for gdb
//
//
// Copyright (c) 2012 Kåre Särs <kare.sars@iki.fi>
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License version 2 as published by the Free Software Foundation.
//
//  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 "advanced_settings.h"

#ifdef WIN32
static const QLatin1Char pathSeparator(';');
#else
static const QLatin1Char pathSeparator(':');
#endif

#include <QFileDialog>

AdvancedGDBSettings::AdvancedGDBSettings(QWidget *parent) : QDialog(parent)
{
    setupUi(this);
    u_gdbBrowse->setIcon(QIcon::fromTheme(QStringLiteral("application-x-ms-dos-executable")));
    connect(u_gdbBrowse, &QToolButton::clicked, this, &AdvancedGDBSettings::slotBrowseGDB);

    u_setSoPrefix->setIcon(QIcon::fromTheme(QStringLiteral("folder")));
    connect(u_setSoPrefix, &QToolButton::clicked, this, &AdvancedGDBSettings::slotSetSoPrefix);

    u_addSoSearchPath->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
    u_delSoSearchPath->setIcon(QIcon::fromTheme(QStringLiteral("list-remove")));
    connect(u_addSoSearchPath, &QToolButton::clicked, this, &AdvancedGDBSettings::slotAddSoPath);
    connect(u_delSoSearchPath, &QToolButton::clicked, this, &AdvancedGDBSettings::slotDelSoPath);

    u_addSrcPath->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
    u_delSrcPath->setIcon(QIcon::fromTheme(QStringLiteral("list-remove")));
    connect(u_addSrcPath, &QToolButton::clicked, this, &AdvancedGDBSettings::slotAddSrcPath);
    connect(u_delSrcPath, &QToolButton::clicked, this, &AdvancedGDBSettings::slotDelSrcPath);

    connect(u_buttonBox, &QDialogButtonBox::accepted, this, &AdvancedGDBSettings::accept);
    connect(u_buttonBox, &QDialogButtonBox::rejected, this, &AdvancedGDBSettings::reject);

    connect(u_localRemote, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &AdvancedGDBSettings::slotLocalRemoteChanged);
}

AdvancedGDBSettings::~AdvancedGDBSettings()
{
}

const QStringList AdvancedGDBSettings::configs() const
{
    QStringList tmp;

    tmp << u_gdbCmd->text();
    switch(u_localRemote->currentIndex()) {
        case 1:
            tmp << QStringLiteral("target remote %1:%2").arg(u_tcpHost->text(), u_tcpPort->text());
            tmp << QString();
            break;
        case 2:
            tmp << QStringLiteral("target remote %1").arg(u_ttyPort->text());
            tmp << QStringLiteral("set remotebaud %1").arg(u_baudCombo->currentText());
            break;
        default:
            tmp << QString();
            tmp << QString();
    }
    if (!u_soAbsPrefix->text().isEmpty()) {
        tmp << QStringLiteral("set solib-absolute-prefix %1").arg(u_soAbsPrefix->text());
    }
    else {
        tmp << QString();
    }

    if (u_soSearchPaths->count() > 0) {
        QString paths = QStringLiteral("set solib-search-path ");
        for (int i=0; i<u_soSearchPaths->count(); ++i) {
            if (i!=0) paths += pathSeparator;
            paths += u_soSearchPaths->item(i)->text();
        }
        tmp << paths;
    }
    else {
        tmp << QString();
    }

    if (u_srcPaths->count() > 0) {
        QString paths = QStringLiteral("set directories ");
        for (int i=0; i<u_srcPaths->count(); ++i) {
            if (i!=0) paths += pathSeparator;
            paths += u_srcPaths->item(i)->text();
        }
        tmp << paths;
    }
    else {
        tmp << QString();
    }
    tmp << u_customInit->toPlainText().split(QLatin1Char('\n'));

    return tmp;
}

void AdvancedGDBSettings::setConfigs(const QStringList &cfgs)
{
    // clear all info
    u_gdbCmd->setText(QStringLiteral("gdb"));
    u_localRemote->setCurrentIndex(0);
    u_soAbsPrefix->clear();
    u_soSearchPaths->clear();
    u_srcPaths->clear();
    u_customInit->clear();
    u_tcpHost->setText(QString());
    u_tcpPort->setText(QString());
    u_ttyPort->setText(QString());
    u_baudCombo->setCurrentIndex(0);

    // GDB
    if (cfgs.count() <= GDBIndex) return;
    u_gdbCmd->setText(cfgs[GDBIndex]);

    // Local / Remote
    if (cfgs.count() <= LocalRemoteIndex) return;

    int start;
    int end;
    if (cfgs[LocalRemoteIndex].isEmpty()) {
        u_localRemote->setCurrentIndex(0);
        u_remoteStack->setCurrentIndex(0);
    }
    else if (cfgs[LocalRemoteIndex].contains(pathSeparator)) {
        u_localRemote->setCurrentIndex(1);
        u_remoteStack->setCurrentIndex(1);
        start = cfgs[LocalRemoteIndex].lastIndexOf(QLatin1Char(' '));
        end = cfgs[LocalRemoteIndex].indexOf(pathSeparator);
        u_tcpHost->setText(cfgs[LocalRemoteIndex].mid(start+1, end-start-1));
        u_tcpPort->setText(cfgs[LocalRemoteIndex].mid(end+1));
    }
    else {
        u_localRemote->setCurrentIndex(2);
        u_remoteStack->setCurrentIndex(2);
        start = cfgs[LocalRemoteIndex].lastIndexOf(QLatin1Char(' '));
        u_ttyPort->setText(cfgs[LocalRemoteIndex].mid(start+1));

        start = cfgs[RemoteBaudIndex].lastIndexOf(QLatin1Char(' '));
        setComboText(u_baudCombo, cfgs[RemoteBaudIndex].mid(start+1));
    }

    // Solib absolute path
    if (cfgs.count() <= SoAbsoluteIndex) return;
    start = 26; // "set solib-absolute-prefix "
    u_soAbsPrefix->setText(cfgs[SoAbsoluteIndex].mid(start));

    // Solib search path
    if (cfgs.count() <= SoRelativeIndex) return;
    start = 22; // "set solib-search-path "
    QString tmp = cfgs[SoRelativeIndex].mid(start);
    u_soSearchPaths->addItems(tmp.split(pathSeparator));

    if (cfgs.count() <= SrcPathsIndex) return;
    start = 16; // "set directories "
    tmp = cfgs[SrcPathsIndex].mid(start);
    u_srcPaths->addItems(tmp.split(pathSeparator));

    // Custom init
    for (int i=CustomStartIndex; i<cfgs.count(); i++) {
        u_customInit->appendPlainText(cfgs[i]);
    }

    slotLocalRemoteChanged();
}

void AdvancedGDBSettings::slotBrowseGDB()
{
    u_gdbCmd->setText(QFileDialog::getOpenFileName(this, QString(), u_gdbCmd->text(), QStringLiteral("application/x-executable")));
    if (u_gdbCmd->text().isEmpty()) {
        u_gdbCmd->setText(QStringLiteral("gdb"));
    }
}

void AdvancedGDBSettings::setComboText(QComboBox *combo, const QString &str)
{
    if (!combo) return;

    for (int i=0; i<combo->count(); i++) {
        if (combo->itemText(i) == str) {
            combo->setCurrentIndex(i);
            return;
        }
    }
    // The string was not found -> add it
    combo->addItem(str);
    combo->setCurrentIndex(combo->count()-1);
}

void AdvancedGDBSettings::slotSetSoPrefix()
{
    QString prefix = QFileDialog::getExistingDirectory(this);
    if (prefix.isEmpty()) return;

    u_soAbsPrefix->setText(prefix);
}

void AdvancedGDBSettings::slotAddSoPath()
{
    QString path = QFileDialog::getExistingDirectory(this);
    if (path.isEmpty()) return;

    u_soSearchPaths->addItem(path);
}

void AdvancedGDBSettings::slotDelSoPath()
{
    QListWidgetItem *item = u_soSearchPaths->takeItem(u_soSearchPaths->currentRow());
    delete item;
}


void AdvancedGDBSettings::slotAddSrcPath()
{
    QString path = QFileDialog::getExistingDirectory(this);
    if (path.isEmpty()) return;

    u_srcPaths->addItem(path);
}

void AdvancedGDBSettings::slotDelSrcPath()
{
    QListWidgetItem *item = u_srcPaths->takeItem(u_srcPaths->currentRow());
    delete item;
}


void AdvancedGDBSettings::slotLocalRemoteChanged()
{
    u_soAbsPrefixLabel->setEnabled(u_localRemote->currentIndex() != 0);
    u_soSearchLabel->setEnabled(u_localRemote->currentIndex() != 0);
    u_soAbsPrefix->setEnabled(u_localRemote->currentIndex() != 0);
    u_soSearchPaths->setEnabled(u_localRemote->currentIndex() != 0);
    u_setSoPrefix->setEnabled(u_localRemote->currentIndex() != 0);
    u_addDelSoPaths->setEnabled(u_localRemote->currentIndex() != 0);
}
