// prefs.cpp
//
// This program is free software. See the file COPYING for details.
// Author: Mattias Engdegård, 1997-1999

#include "prefs.h"
#include "proc.h"
#include "qps.h"
#include <QLabel>
#include <QVBoxLayout>
#include <QGroupBox>
#include <qstring.h>
#include <QtGui>
#include <QApplication>
#include <QFontComboBox>

//#include <qstylefactory.h>
#include "qps.h"
extern Qps *qps;

extern QFontComboBox *font_cb;
// class that validates input for the "swap warning limit" field
class Swapvalid : public QValidator
{
  public:
    Swapvalid(QWidget *parent) : QValidator(parent) {}
    virtual State validate(QString &s, int &) const;
};

struct Boxvar
{
    const char *text;
    bool *variable;
    // CrossBox *cb;
    QCheckBox *cb;
};

static Boxvar general_boxes[] = {
    // {"Graphic Load Display", &Qps::show_load_graph, 0},
    // {"Graphic CPU Display", &Qps::show_cpu_bar, 0},
    //{"Minimized on Close Button", &Qps::flag_systray, 0},
    {"Exit On Close Button", &Qps::flag_exit, 0},

    // TEMPO
    //  {"Use Tab-View", &Qps::flag_useTabView, 0},
    //   {"Hide qps in Linear mode", &Qps::flag_qps_hide, 0},
    //  {"Load Graph in Icon", &Qps::load_in_icon, 0},
    //  {"Selection: Copy PIDs to Clipboard", &Qps::pids_to_selection, 0},
    //   {"show underdevelopment ", &Qps::flag_devel, 0},
    //   {"Vertical CPU Bar (under development)", &Qps::vertical_cpu_bar, 0},
    {0, 0, 0}};

#ifdef LINUX
static Boxvar sockinfo_boxes[] = {
    {"Host Name Lookup", &Qps::hostname_lookup, 0},
    {"Service Name Lookup", &Qps::service_lookup, 0},
    {0, 0, 0}};
#endif

static Boxvar tree_boxes[] = {{"Disclosure Triangles", &Qps::tree_gadgets, 0},
                              {"Branch Lines", &Qps::tree_lines, 0},
                              {0, 0, 0}};

static Boxvar misc_boxes[] = {
    {"Auto Save Settings on Exit", &Qps::auto_save_options, 0},
    {"Selection: Copy PIDs to Clipboard", &Qps::pids_to_selection, 0},
#ifdef SOLARIS
    {"Normalize NICE", &Qps::normalize_nice, 0},
    {"Use pmap for Map Names", &Qps::use_pmap, 0},
#endif
    {0, 0, 0}};

struct Cbgroup
{
    const char *caption;
    Boxvar *boxvar;
};

static Cbgroup groups[] = {{"General", general_boxes},
#ifdef LINUX
//    {"Socket Info Window", sockinfo_boxes},
#endif
                           //   {"Tree View", tree_boxes},
                           //    {"Miscellaneous", misc_boxes},
                           {0, 0}};

void find_fontsets();
// dual use function: both validate and apply changes
QValidator::State Swapvalid::validate(QString &s, int &) const
{
    // only accept /^[0-9]*[%kKmM]?$/
    int len = s.length();
    int i = 0;
    while (i < len && s[i] >= '0' && s[i] <= '9')
        i++;
    if ((i < len && QString("kKmM%").contains(s[i]) == 0) || i < len - 1)
        return Invalid;
    if (s[i] == 'k')
        s[i] = 'K';
    if (s[i] == 'm')
        s[i] = 'M';
    // int val = atoi((const char *)s);
    int val = s.toInt();
    bool percent;
    if (s[i] == '%')
    {
        percent = true;
    }
    else
    {
        percent = false;
        if (s[i] == 'M')
            val <<= 10;
    }
    Qps::swaplimit = val;
    Qps::swaplim_percent = percent;
    return Acceptable;
}

Preferences::Preferences() : QDialog()
{
    int flag_test = 0;
    setWindowTitle("Preferences");
    QVBoxLayout *v_layout = new QVBoxLayout;

    if (flag_test)
    {
        QTabWidget *tbar = new QTabWidget(this);
        QWidget *w = new QWidget(this);
        tbar->addTab(w, "&Setting");
        w->setLayout(v_layout);
    }
    else
        setLayout(v_layout);

    v_layout->setSpacing(1);
    // v_layout->setSpacing(1);
    const int border_x = 10;
    int min_x = 0;

    for (Cbgroup *g = groups; g->caption; g++)
    {
        QGroupBox *grp = new QGroupBox(g->caption, this);
        QVBoxLayout *vbox = new QVBoxLayout;
        for (Boxvar *b = g->boxvar; b->text; b++)
        {
            b->cb = new QCheckBox(b->text, grp);
            vbox->addWidget(b->cb);
            connect(b->cb, SIGNAL(clicked()), SLOT(update_reality()));
            // -> EMIT prefs_change()
        }
        grp->setLayout(vbox);
        v_layout->addWidget(grp);
    }
    update_boxes();

    /*
    QGroupBox *wgrp = new QGroupBox("Swap Warning", this);
  QHBoxLayout *hl = new QHBoxLayout;
    wgrp->setLayout(hl);
    QLabel *lbl = new QLabel("Warn when free swap below", wgrp);
    QLineEdit *swaped = new QLineEdit(wgrp);
  hl->addWidget(lbl);
  hl->addWidget(swaped);
    //swaped->setAlignment (  Qt::AlignRight );
    QString s;
    if(Qps::swaplim_percent) {
            s.sprintf("%d%%", Qps::swaplimit);
    } else {
            if(Qps::swaplimit >= 1024 && (Qps::swaplimit & 0x7ff) == 0)
                    s.sprintf("%dM", Qps::swaplimit >> 10);
            else
                    s.sprintf("%dK", Qps::swaplimit);
    }
    swaped->setText(s);
    swaped->setValidator(new Swapvalid(this));
    connect(swaped, SIGNAL(textChanged(const QString &)),
  SIGNAL(prefs_change()));
    v_layout->addWidget(wgrp);
    */

    rb_totalcpu = NULL; // tmp

    if (QPS_PROCVIEW_CPU_NUM() > 1)
    {
        QGroupBox *grp_cpu = new QGroupBox("%CPU divided by", this);
        QVBoxLayout *vboxlayout = new QVBoxLayout;
        QHBoxLayout *hbox = new QHBoxLayout;
        vboxlayout->addLayout(hbox);

        // num_cpus
        QString str;
        str.sprintf("Total cpu: %d", QPS_PROCVIEW_CPU_NUM());
        rb_totalcpu = new QRadioButton(str, grp_cpu);
        QRadioButton *rb2 = new QRadioButton("Single cpu: 1", grp_cpu);
        if (!Procview::flag_pcpu_single)
            rb_totalcpu->setChecked(true);
        else
            rb2->setChecked(true);

        rb_totalcpu->setToolTip("default");
        rb2->setToolTip("for developer");
        hbox->addWidget(rb_totalcpu);
        hbox->addWidget(rb2);
        grp_cpu->setLayout(vboxlayout);
        v_layout->addWidget(grp_cpu);

        connect(rb_totalcpu, SIGNAL(clicked()), this, SLOT(update_config()));
        connect(rb2, SIGNAL(clicked()), this, SLOT(update_config()));
    }

    // Appearance ====================================
    if (font_cb == NULL)
    {
        font_cb = new QFontComboBox(this); // preload
        font_cb->setWritingSystem(QFontDatabase::Latin);
        font_cb->setCurrentFont(QApplication::font());

        // remove Some Ugly Font : hershey...
        // printf("size=%d\n",font_cb->count());
        for (int i = 0; i < font_cb->count();)
        {
            QString name = font_cb->itemText(i);
            if (name.contains("hershey", Qt::CaseInsensitive) == true)
            {
                //		printf("%s\n",qPrintable(name));
                font_cb->removeItem(i);
            }
            else
                i++;
        }
    }

    if (font_cb)
    {
        font_cb->show();

        QGroupBox *gbox = new QGroupBox("Appearance", this);
        QVBoxLayout *vbox = new QVBoxLayout;
        QHBoxLayout *hbox = new QHBoxLayout();

        psizecombo = new QComboBox(this);
        hbox->addWidget(font_cb);
        hbox->addWidget(psizecombo);
        vbox->addLayout(hbox);
        gbox->setLayout(vbox);
        v_layout->addWidget(gbox);

        // connect(font_cb, SIGNAL(activated( int)),this,
        // SLOT(font_changed(int)));
        connect(font_cb, SIGNAL(activated(int)), this, SLOT(font_changed(int)));
        connect(psizecombo, SIGNAL(activated(int)), SLOT(font_changed(int)));

        // add to font size
        init_font_size();
    }

    /*
    // Style, Themes ==================================
    QLabel *label3 = new QLabel("Themes", font_grp);
    QComboBox *theme_combo = new QComboBox(font_grp);

    QStringList styles = QStyleFactory::keys();
  styles.sort();
  theme_combo->insertStringList(styles);

    QString currentstyle;
    currentstyle = QApplication::style().className();
  */

    QPushButton *saveButton = new QPushButton("OK", this);
    // saveButton->setFocusPolicy(QWidget::NoFocus);
    saveButton->setFocus();
    saveButton->setDefault(true);
    v_layout->addWidget(saveButton);
    // v_layout->freeze();

    connect(saveButton, SIGNAL(clicked()), SLOT(closed()));
}

//
void Preferences::init_font_size()
{
    // 	QFontDatabase db;
    //	QStringList families ( WritingSystem writingSystem = Any ) const
    //	QStringList families = db.families(QFontDatabase::Latin);
    //	QStringList extra;
    psizecombo->clear();
    int i, idx = 0;
    for (i = 5; i < 24; i++)
        psizecombo->insertItem(idx++, QString::number(i));

    // find current font size
    i = 0;
    for (int psize = QApplication::font().pointSize(); i < psizecombo->count();
         ++i)
    {
        const int sz = psizecombo->itemText(i).toInt();
        if (sz == psize)
        {
            psizecombo->setCurrentIndex(i);
            break;
        }
    }
}

// slot: update check boxes to reflect current status
void Preferences::update_boxes()
{
    for (Cbgroup *g = groups; g->caption; g++)
        for (Boxvar *b = g->boxvar; b->text; b++)
            b->cb->setChecked(*b->variable);
}

// slot: update flags and repaint to reflect state of check boxes
void Preferences::update_reality()
{
    for (Cbgroup *g = groups; g->caption; g++)
        for (Boxvar *b = g->boxvar; b->text; b++)
            *b->variable = b->cb->isChecked();
    emit prefs_change();
}

void Preferences::update_config()
{
    if (rb_totalcpu and rb_totalcpu->isChecked() == true)
        Procview::flag_pcpu_single = false;
    else
        Procview::flag_pcpu_single = true;
}

void Preferences::closed()
{
    //	delete font_cb;	font_cb==NULL;
    //	font_cb->clear();
    update_config();
    hide();
    emit prefs_change();
}

// work
void Preferences::font_changed(int i)
{
    int size = psizecombo->currentText().toInt();
    QFont font = font_cb->currentFont();
    font.setPointSize(size);

    QApplication::setFont(font);
}

// DRAFT CODE:
void Preferences::fontset_changed(int i) {}
