/*
 * 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/>.
 */

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

#include "qziontextblock_p.h"
#include "qziontextblock.h"
#include "qzionmacros.h"


QZionTextBlock::QZionTextBlock(QZionAbstractCanvas *canvas)
    : QZionObject(canvas), _QZionTextBlock_data(new QZionTextBlockPrivate())
{
    QZD(QZionTextBlock);
    d->owner = this;
    d->text = "";

    QPalette palette;
    palette.setBrush(QPalette::Window, QBrush(QColor(255, 255, 255, 0)));
    d->page.setPalette(palette);
    d->page.mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
    d->page.mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);

    QObject::connect(&(d->page), SIGNAL(loadFinished(bool)),
                     this, SIGNAL(contentsChanged()));
    QObject::connect(&(d->page), SIGNAL(loadFinished(bool)),
                     this, SIGNAL(contentsLoadFinished()));
    QObject::connect(&(d->page), SIGNAL(loadProgress(int)),
                     this, SIGNAL(contentsChanged()));

    QObject::connect(&(d->page), SIGNAL(loadFinished(bool)),
                     d, SLOT(resizeContents()));

    d->page.mainFrame()->setHtml(d->text);
}

QZionTextBlock::QZionTextBlock(QZionAbstractCanvas *canvas, const QString &text)
    : QZionObject(canvas), _QZionTextBlock_data(new QZionTextBlockPrivate())
{
    QZD(QZionTextBlock);
    d->owner = this;
    d->text = text;

    QPalette palette;
    palette.setBrush(QPalette::Window, QBrush(QColor(255, 255, 255, 0)));
    d->page.setPalette(palette);
    d->page.mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
    d->page.mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);

    QObject::connect(&(d->page), SIGNAL(loadFinished(bool)),
                     this, SIGNAL(contentsChanged()));
    QObject::connect(&(d->page), SIGNAL(loadFinished(bool)),
                     this, SIGNAL(contentsLoadFinished()));
    QObject::connect(&(d->page), SIGNAL(loadProgress(int)),
                     this, SIGNAL(contentsChanged()));

    QObject::connect(&(d->page), SIGNAL(loadFinished(bool)),
                     d, SLOT(resizeContents()));

    d->page.mainFrame()->setHtml(d->text);
}

QZionTextBlock::~QZionTextBlock()
{
    delete _QZionTextBlock_data;
}

QSize QZionTextBlock::size() const
{
    QZD(QZionTextBlock);
    return d->size;
}

QSize QZionTextBlock::contentsSize() const
{
    QZD(QZionTextBlock);
    return d->page.mainFrame()->contentsSize() * d->scale;
}

int QZionTextBlock::preferredWidth()
{
    QZD(QZionTextBlock);
    return d->preferredWidth;
}

void QZionTextBlock::setPreferredWidth(const int width)
{
    QZD(QZionTextBlock);
    d->preferredWidth = width;
    // need to do this to get the correct height (webkit way)
    d->page.setViewportSize(QSize(width, 1));
    d->page.setViewportSize(d->page.mainFrame()->contentsSize());
    d->refresh();
}

void QZionTextBlock::setSize(const QSize &size)
{
    QZD(QZionTextBlock);
    QZionObject::setSize(size);
    d->size = size;

    if (d->preferredWidth)
        return;

    d->page.setViewportSize(QSize(size.width(), 1));
    d->page.setViewportSize(d->page.mainFrame()->contentsSize());
    d->refresh();
}

QColor QZionTextBlock::color() const
{
    return QColor(255, 255, 255, 0);
}

void QZionTextBlock::setColor(const QColor &color)
{
    Q_UNUSED(color);
}

QString QZionTextBlock::text() const
{
    QZD(QZionTextBlock);
    return d->text;
}

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

    if (d->text != text) {
        d->text = text;
        d->page.mainFrame()->setHtml(d->text);
        d->refresh();
    }
}

QRect QZionTextBlock::rect() const
{
    return QRect(pos(), size());
}

double QZionTextBlock::scale()
{
    QZD(QZionTextBlock);
    return d->scale;
}

void QZionTextBlock::setScale(double factor)
{
    QZD(QZionTextBlock);
    d->scale = factor;
    d->refresh();
}

QPixmap QZionTextBlock::toPixmap()
{
    QZD(QZionTextBlock);
    QPixmap pixmap(d->page.viewportSize());
    pixmap.fill();
    QPainter painter(&pixmap);

    d->page.mainFrame()->render(&painter);

    return pixmap;
}

QImage QZionTextBlock::toImage()
{
    QZD(QZionTextBlock);
    QImage image(d->page.viewportSize(), QImage::Format_RGB32);
    // Fills white
    image.fill(0xFFFFFF);
    QPainter painter(&image);

    d->page.mainFrame()->render(&painter);

    return image;
}


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

    painter->translate(pos());
    painter->scale(d->scale, d->scale);

    QRect scaledRect = rect().translated(-pos());
    scaledRect.setSize(QSize(scaledRect.width() / d->scale,
                             scaledRect.height() / d->scale));
    QRegion clipRegion = painter->clipRegion().boundingRect() & scaledRect;
    d->page.mainFrame()->render(painter, clipRegion);

    painter->translate(-pos());
}
