/*
 * Copyright (C) 2008 Instituto Nokia de Tecnologia. All rights reserved.
 *
 * This file is part of QZion.
 *
 * QZion 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 3 of the License, or
 * (at your option) any later version.
 *
 * QZion 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 QZion.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *
 *  Copyright 2006 Maurizio Monge <maurizio.monge@gmail.com>
 *
 *  BSD License
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Attention: note that even being named "BSD License" by the
 * copyright holder, the license above is a variation of the license
 * known as BSD License.  This variation is compatible with GNU GPL.
 */

#include <QDebug>
#include <QRegion>
#include <QPainter>
#include <QApplication>
#include <QPaintEvent>

#include "qziontext.h"
#include "qziontext_p.h"

#include "qzionmacros.h"
#include "qzionobject_p.h"


QZionText::QZionText(QZionAbstractCanvas *canvas, const QString &text,
                     const QFont &font, const QColor &color)
    : QZionObject(canvas), _QZionText_data(new QZionTextPrivate(text, font, color))
{
    _QZionText_data->owner = this;
}

QZionText::QZionText(QZionAbstractCanvas *canvas)
    : QZionObject(canvas), _QZionText_data(new QZionTextPrivate(""))
{
    _QZionText_data->owner = this;
}

QZionText::~QZionText()
{
    delete _QZionText_data;
}


QSize QZionText::size() const
{
    QZD(QZionText);

    return d->size;
}

void QZionText::setSize(const QSize &size)
{
    QZD(QZionText);

    QZionObject::setSize(size);
    d->size = size;
    d->refresh();
}

QZionText::TextStyle QZionText::style() const
{
    QZD(QZionText);
    return d->style;
}


void QZionText::setStyle(const QZionText::TextStyle style)
{
    QZD(QZionText);
    if (d->style != style) {
        d->style = style;
        d->refresh(true);
    }
}


QString QZionText::text() const
{
    QZD(QZionText);

    return d->text;
}

void QZionText::setText(const QString &text)
{
    QZD(QZionText);

    if (d->text != text) {
        d->text = text;
        d->refresh(true);
    }
}

QColor QZionText::color() const
{
    QZD(QZionText);

    return d->color;
}

void QZionText::setColor(const QColor &color)
{
    QZD(QZionText);

    setOpacity(color.alpha());
    d->color.setRgb(color.rgb());
    d->refresh();
}

QColor QZionText::textColor() const
{
    // XXX: match QGV's behavior
    return color();
}

void QZionText::setTextColor(const QColor &color)
{
    // XXX: match QGV's behavior
    setColor(color);
}

QColor QZionText::outlineColor() const
{
    QZD(QZionText);
    return d->color2;
}


void QZionText::setOutlineColor(const QColor &color)
{
    QZD(QZionText);
    d->color2.setRgb(color.rgb());
    d->refresh();
}


QColor QZionText::shadowColor() const
{
    QZD(QZionText);
    return d->color3;
}


void QZionText::setShadowColor(const QColor &color)
{
    QZD(QZionText);
    d->color3.setRgb(color.rgb());
    d->refresh();
}


QFont QZionText::font() const
{
    QZD(QZionText);
    return d->font;
}

void QZionText::setFont(const QFont &font)
{
    QZD(QZionText);
    d->font = font;
    d->refresh(true);
}

QPointF QZionText::alignment() const
{
    QZD(QZionText);

    return d->alignment;
}

void QZionText::setAlignment(const QPointF &alignment)
{
    QZD(QZionText);

    d->alignment = alignment;
    d->refresh();
}

QRect QZionText::rect() const
{
    QZD(QZionText);
    return d->realBoundingRect();
}

void QZionText::paint(QPainter *painter)
{
    QZD(QZionText);

    painter->setPen(d->color);
    painter->setFont(d->font);

    QRect tileRect = d->realBoundingRect();

    int flags = Qt::TextSingleLine | Qt::AlignLeft;
    QString text;

    if (tileRect.width() == d->size.width()) {
        text = QFontMetricsF(d->font).elidedText(d->text, Qt::ElideRight, tileRect.width());
    } else {
        text = d->text;
    }

    switch (d->style) {
        case NoStyle:
            painter->drawText(tileRect, flags, text);
            break;
        case OutLine:
            {
                int width = 1;

                QPainterPath path;
                QFont outlineFont = QFont(d->font);
                outlineFont.setStyleStrategy(QFont::ForceOutline);

                QPointF basepoint = tileRect.bottomLeft();
                basepoint.setY(basepoint.y() - width
                    - QFontMetrics(outlineFont).descent());

                path.addText(basepoint, outlineFont, text);
                painter->setRenderHint(QPainter::Antialiasing);
                painter->setPen(QPen(d->color3, width, Qt::SolidLine, Qt::RoundCap,
                                Qt::RoundJoin));
                painter->setBrush(d->color);
                painter->drawPath(path);
            }
            break;
        case Shadow:
            d->color3.setAlpha(128);
            painter->setPen(d->color3);
            painter->drawText(tileRect.translated(1, 1), flags, text);

            painter->setPen(d->color);
            painter->drawText(tileRect, flags, text);
            break;
        default:
            break;
    }
}

void QZionText::changed()
{
    QZionObject::changed();
}

// TODO
qreal QZionText::ellipsisAlignment() const
{
    return 0.0;
}

// TODO
void QZionText::setEllipsisAlignment(const qreal alignment)
{

}
