/***************************************************************************
 *   Copyright (c) 2009  Nikolaj Hald Nielsen <nhnFreespirit@gmail.com>    *
 *   Copyright (c) 2009  Roman Jarosz         <kedgedev@gmail.com>         *
 *                                                                         *
 *   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 "TokenWithLayout.h"

#include "TokenDropTarget.h"

#include <QAction>
#include <QHBoxLayout>
#include <KLocalizedString>

#include <QActionGroup>
#include <QContextMenuEvent>
#include <QLayout>
#include <QMenu>
#include <QSlider>
#include <QLCDNumber>

const QString ActionBoldName = QStringLiteral("ActionBold");
const QString ActionItalicName = QStringLiteral("ActionItalic");
const QString ActionAlignLeftName = QStringLiteral("ActionAlignLeft");
const QString ActionAlignCenterName = QStringLiteral("ActionAlignCenter");
const QString ActionAlignRightName = QStringLiteral("ActionAlignRight");

Token *TokenWithLayoutFactory::createToken(const QString &text, const QString &iconName, int value, QWidget *parent)
{
    return new TokenWithLayout(text, iconName, value, parent);
}

TokenWithLayout::TokenWithLayout(const QString &text, const QString &iconName, int value, QWidget *parent)
    : Token(text, iconName, value, parent)
    , m_width(0.0)
{
    m_widthForced = m_width > 0.0;
    m_alignment = Qt::AlignCenter;
    m_bold = false;
    m_italic = false;
    setFocusPolicy(Qt::ClickFocus);
}

TokenWithLayout::~TokenWithLayout()
{
}

void TokenWithLayout::fillMenu(QMenu *menu)
{
    QAction *boldAction = new QAction(QIcon::fromTheme(QStringLiteral("format-text-bold")), i18n("Bold"), menu);
    boldAction->setObjectName(ActionBoldName);
    boldAction->setCheckable(true);
    boldAction->setChecked(m_bold);

    QAction *italicAction = new QAction(QIcon::fromTheme(QStringLiteral("format-text-italic")), i18n("Italic"), menu);
    italicAction->setObjectName(ActionItalicName);
    italicAction->setCheckable(true);
    italicAction->setChecked(m_italic);

    QAction *alignLeftAction = new QAction(QIcon::fromTheme(QStringLiteral("format-justify-left")), i18n("Left"), menu);
    QAction *alignCenterAction = new QAction(QIcon::fromTheme(QStringLiteral("format-justify-center")), i18n("Center"), menu);
    QAction *alignRightAction = new QAction(QIcon::fromTheme(QStringLiteral("format-justify-right")), i18n("Right"), menu);
    alignLeftAction->setObjectName(ActionAlignLeftName);
    alignLeftAction->setCheckable(true);
    alignCenterAction->setObjectName(ActionAlignCenterName);
    alignCenterAction->setCheckable(true);
    alignRightAction->setObjectName(ActionAlignRightName);
    alignRightAction->setCheckable(true);

    if (m_alignment & Qt::AlignLeft) {
        alignLeftAction->setChecked(true);
    } else if (m_alignment & Qt::AlignHCenter) {
        alignCenterAction->setChecked(true);
    } else if (m_alignment & Qt::AlignRight) {
        alignRightAction->setChecked(true);
    }

    QActionGroup *alignmentGroup = new QActionGroup(menu);
    alignmentGroup->addAction(alignLeftAction);
    alignmentGroup->addAction(alignCenterAction);
    alignmentGroup->addAction(alignRightAction);

    menu->addAction(boldAction);
    menu->addAction(italicAction);
    menu->addSeparator()->setText(i18n("Alignment"));
    menu->addAction(alignLeftAction);
    menu->addAction(alignCenterAction);
    menu->addAction(alignRightAction);
    menu->addSeparator()->setText(i18n("Width"));
    menu->adjustSize();

    int orgHeight = menu->height();

    QWidget *sliderBox = new QWidget(menu);
    QHBoxLayout *sliderBoxHBoxLayout = new QHBoxLayout(sliderBox);
    sliderBoxHBoxLayout->setMargin(0);
    sliderBox->setFixedWidth(menu->width() - 4);
    sliderBox->move(sliderBox->pos().x() + 2, orgHeight);

    QSlider *slider = new QSlider(Qt::Horizontal, sliderBox);
    sliderBoxHBoxLayout->addWidget(slider);
    slider->setMaximum(100);
    slider->setMinimum(0);

    // this should really not be done here as it makes upward assumptions
    // it was however done in setWidth with similar upward assumptions as well
    // solution: the popup stuff -iff- should be done in the dialog or the editWidget
    if (parentWidget()) {
        if (TokenDropTarget *editWidget = qobject_cast<TokenDropTarget *>(parentWidget())) {
            qreal spareWidth = 100.0;
            int row = editWidget->row(this);
            if (row > -1) {
                QList<Token *> tokens = editWidget->drags(row);
                foreach (Token *t, tokens) {
                    if (t == this) {
                        continue;
                    }
                    if (TokenWithLayout *twl = qobject_cast<TokenWithLayout *>(t)) {
                        spareWidth -= twl->width() * 100.0;
                    }
                }
            }
            slider->setMaximum(qMax<qreal>(spareWidth, 0.0));
        }
    }
    slider->setValue(m_width * 100.0);

    QLCDNumber *sizeLabel = new QLCDNumber(3, sliderBox);
    sliderBoxHBoxLayout->addWidget(sizeLabel);
    sizeLabel->display(m_width * 100.0);

    connect(slider, SIGNAL(valueChanged(int)), sizeLabel, SLOT(display(int)));
    connect(slider, SIGNAL(valueChanged(int)), this, SLOT(setWidth(int)));

    menu->setFixedHeight(orgHeight + slider->height());

    slider->setFixedWidth(menu->width() - 4);
}

void TokenWithLayout::menuExecuted(const QAction *action)
{
    if (action->objectName() == ActionAlignLeftName) {
        setAlignment(Qt::AlignLeft);
    } else if (action->objectName() == ActionAlignCenterName) {
        setAlignment(Qt::AlignCenter);
    } else if (action->objectName() == ActionAlignRightName) {
        setAlignment(Qt::AlignRight);
    } else if (action->objectName() == ActionBoldName) {
        setBold(action->isChecked());
    } else if (action->objectName() == ActionItalicName) {
        setItalic(action->isChecked());
    }
}

void TokenWithLayout::contextMenuEvent(QContextMenuEvent *event)
{
    QMenu *menu = new QMenu();

    menu->setTitle(i18n("Layout"));

    fillMenu(menu);

    QAction *action = menu->exec(mapToGlobal(event->pos()));
    if (action) {
        menuExecuted(action);
    }

    delete menu;
}

Qt::Alignment TokenWithLayout::alignment()
{
    return m_alignment;
}

void TokenWithLayout::setAlignment(Qt::Alignment alignment)
{
    if (m_alignment == alignment) {
        return;
    }

    m_alignment = alignment;
    m_label->setAlignment(alignment);
    emit changed();
}

void TokenWithLayout::setAlignLeft(bool b)
{
    if (b) {
        setAlignment(Qt::AlignLeft);
    }
}

void TokenWithLayout::setAlignCenter(bool b)
{
    if (b) {
        setAlignment(Qt::AlignCenter);
    }
}

void TokenWithLayout::setAlignRight(bool b)
{
    if (b) {
        setAlignment(Qt::AlignRight);
    }
}

bool TokenWithLayout::bold() const
{
    return m_bold;
}

void TokenWithLayout::setBold(bool bold)
{
    if (m_bold == bold) {
        return;
    }

    m_bold = bold;
    QFont font = m_label->font();
    font.setBold(bold);
    m_label->setFont(font);
    emit changed();
}

void TokenWithLayout::setPrefix(const QString &string)
{
    if (m_prefix == string) {
        return;
    }

    m_prefix = string;
    emit changed();
}

void TokenWithLayout::setSuffix(const QString &string)
{
    if (m_suffix == string) {
        return;
    }

    m_suffix = string;
    emit changed();
}

void TokenWithLayout::setWidth(int size)
{
    m_width = qMax(qMin(1.0, size/100.0), 0.0);
    if ((m_width) > 0.0) {
        m_widthForced = true;
    }

    emit changed();
}

void TokenWithLayout::setWidthForced(bool on)
{
    m_widthForced = on;
}

qreal TokenWithLayout::width() const
{
    return m_width;
}

bool TokenWithLayout::italic() const
{
    return m_italic;
}

void TokenWithLayout::setItalic(bool italic)
{
    if (m_italic == italic) {
        return;
    }

    m_italic = italic;
    QFont font = m_label->font();
    font.setItalic(italic);
    m_label->setFont(font);

    emit changed();
}
