/*
    Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
                  2004, 2005 Rob Buis <buis@kde.org>

    This file is part of the KDE project

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    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., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include "config.h"
#include <kdom/core/AttrImpl.h>

#include <kcanvas/KCanvas.h>
#include <kcanvas/KCanvasMatrix.h>
#include <kcanvas/KCanvasRegistry.h>
#include <kcanvas/KCanvasContainer.h>
#include <kcanvas/KCanvasCreator.h>
#include <kcanvas/KCanvasImage.h>
#include <kcanvas/device/KRenderingDevice.h>
#include <kcanvas/device/KRenderingPaintServerPattern.h>

#include "ksvg.h"
#include "svgattrs.h"
#include "SVGHelper.h"
#include "SVGMatrixImpl.h"
#include "SVGDocumentImpl.h"
#include "SVGSVGElementImpl.h"
#include "SVGTransformableImpl.h"
#include "SVGTransformListImpl.h"
#include "KCanvasRenderingStyle.h"
#include "SVGPatternElementImpl.h"
#include "SVGAnimatedStringImpl.h"
#include "SVGAnimatedLengthImpl.h"
#include "SVGDOMImplementationImpl.h"
#include "SVGAnimatedEnumerationImpl.h"
#include "SVGAnimatedTransformListImpl.h"

using namespace KSVG;

SVGPatternElementImpl::SVGPatternElementImpl(KDOM::DocumentPtr *doc, KDOM::NodeImpl::Id id, KDOM::DOMStringImpl *prefix) : SVGStyledElementImpl(doc, id, prefix), SVGURIReferenceImpl(), SVGTestsImpl(), SVGLangSpaceImpl(), SVGExternalResourcesRequiredImpl(), SVGFitToViewBoxImpl(), KCanvasResourceListener()
{
    m_patternUnits = 0;
    m_patternTransform = 0;
    m_patternContentUnits = 0;
    m_x = m_y = m_width = m_height = 0;

    m_tile = 0;
    m_paintServer = 0;
    m_ignoreAttributeChanges = false;
}

SVGPatternElementImpl::~SVGPatternElementImpl()
{
    if(m_x)
        m_x->deref();
    if(m_y)
        m_y->deref();
    if(m_width)
        m_width->deref();
    if(m_height)
        m_height->deref();
    if(m_patternUnits)
        m_patternUnits->deref();
    if(m_patternContentUnits)
        m_patternContentUnits->deref();
    if(m_patternTransform)
        m_patternTransform->deref();
    if (m_canvasItem)
        delete m_canvasItem;
}

SVGAnimatedEnumerationImpl *SVGPatternElementImpl::patternUnits() const
{
    if(!m_patternUnits)
    {
        lazy_create<SVGAnimatedEnumerationImpl>(m_patternUnits, this);
        m_patternUnits->setBaseVal(SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
    }

    return m_patternUnits;
}

SVGAnimatedEnumerationImpl *SVGPatternElementImpl::patternContentUnits() const
{
    if(!m_patternContentUnits)
    {
        lazy_create<SVGAnimatedEnumerationImpl>(m_patternContentUnits, this);
        m_patternContentUnits->setBaseVal(SVG_UNIT_TYPE_USERSPACEONUSE);
    }

    return m_patternContentUnits;
}

SVGAnimatedLengthImpl *SVGPatternElementImpl::x() const
{
    return lazy_create<SVGAnimatedLengthImpl>(m_x, this, LM_WIDTH, viewportElement());
}

SVGAnimatedLengthImpl *SVGPatternElementImpl::y() const
{
    return lazy_create<SVGAnimatedLengthImpl>(m_y, this, LM_HEIGHT, viewportElement());
}

SVGAnimatedLengthImpl *SVGPatternElementImpl::width() const
{
    return lazy_create<SVGAnimatedLengthImpl>(m_width, this, LM_WIDTH, viewportElement());
}

SVGAnimatedLengthImpl *SVGPatternElementImpl::height() const
{
    return lazy_create<SVGAnimatedLengthImpl>(m_height, this, LM_HEIGHT, viewportElement());
}

SVGAnimatedTransformListImpl *SVGPatternElementImpl::patternTransform() const
{
    return lazy_create<SVGAnimatedTransformListImpl>(m_patternTransform, this);
}

void SVGPatternElementImpl::parseAttribute(KDOM::AttributeImpl *attr)
{
    int id = (attr->id() & NodeImpl_IdLocalMask);
    KDOM::DOMString value(attr->value());
    switch(id)
    {
        case ATTR_PATTERNUNITS:
        {
            if(value == "userSpaceOnUse")
                patternUnits()->setBaseVal(SVG_UNIT_TYPE_USERSPACEONUSE);
            else if(value == "objectBoundingBox")
                patternUnits()->setBaseVal(SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
            break;
        }
        case ATTR_PATTERNCONTENTUNITS:
        {
            if(value == "userSpaceOnUse")
                patternContentUnits()->setBaseVal(SVG_UNIT_TYPE_USERSPACEONUSE);
            else if(value == "objectBoundingBox")
                patternContentUnits()->setBaseVal(SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
            break;
        }
        case ATTR_PATTERNTRANSFORM:
        {
            SVGTransformListImpl *patternTransforms = patternTransform()->baseVal();
            SVGTransformableImpl::parseTransformAttribute(patternTransforms, attr->value());
            break;
        }
        case ATTR_X:
        {
            x()->baseVal()->setValueAsString(value.handle());
            break;
        }
        case ATTR_Y:
        {
            y()->baseVal()->setValueAsString(value.handle());
            break;
        }
        case ATTR_WIDTH:
        {
            width()->baseVal()->setValueAsString(value.handle());
            break;
        }
        case ATTR_HEIGHT:
        {
            height()->baseVal()->setValueAsString(value.handle());
            break;
        }
        default:
        {
            if(SVGURIReferenceImpl::parseAttribute(attr)) return;
            if(SVGTestsImpl::parseAttribute(attr)) return;
            if(SVGLangSpaceImpl::parseAttribute(attr)) return;
            if(SVGExternalResourcesRequiredImpl::parseAttribute(attr)) return;
            if(SVGFitToViewBoxImpl::parseAttribute(attr)) return;

            SVGStyledElementImpl::parseAttribute(attr);
        }
    };
}

const SVGStyledElementImpl *SVGPatternElementImpl::pushAttributeContext(const SVGStyledElementImpl *context)
{
    // All attribute's contexts are equal (so just take the one from 'x').
    const SVGStyledElementImpl *restore = x()->baseVal()->context();

    x()->baseVal()->setContext(context);
    y()->baseVal()->setContext(context);
    width()->baseVal()->setContext(context);
    height()->baseVal()->setContext(context);

    return restore;
}

void SVGPatternElementImpl::resourceNotification() const
{
    // We're referenced by a "client", calculate the tile now...
    notifyAttributeChange();
}

void SVGPatternElementImpl::notifyAttributeChange() const
{
    if(!m_paintServer || !m_paintServer->activeClient())
        return;

    if(m_ignoreAttributeChanges)
        return;

    float w = width()->baseVal()->value();
    float h = height()->baseVal()->value();

    QSize newSize = QSize(qRound(w), qRound(h));
    if(m_tile && (m_tile->size() == newSize))
        return;

    m_ignoreAttributeChanges = true;

    // Find first pattern def that has children
    const KDOM::ElementImpl *target = this;

    const KDOM::NodeImpl *test = this;
    while(test && !test->hasChildNodes())
    {
        QString ref = KDOM::DOMString(href()->baseVal()).string();
        test = ownerDocument()->getElementById(KDOM::DOMString(ref.mid(1)).handle());
        if(test && test->id() == ID_PATTERN)
            target = static_cast<const KDOM::ElementImpl *>(test);
    }

    unsigned short savedPatternUnits = patternUnits()->baseVal();
    unsigned short savedPatternContentUnits = patternContentUnits()->baseVal();

    KRenderingPaintServer *refServer = 0;
    QString ref = KDOM::DOMString(href()->baseVal()).string();
    if(!ref.isEmpty())
    {
        SVGDocumentImpl *document = static_cast<SVGDocumentImpl *>(ownerDocument());
        KCanvas *canvas = (document ? document->canvas() : 0);
        Q_ASSERT(canvas != 0);
        
        refServer = canvas->registry()->getPaintServerById(ref.mid(1));
    }

    KCanvasMatrix patternTransformMatrix;
    if(patternTransform()->baseVal()->numberOfItems() > 0)
        patternTransformMatrix = KCanvasMatrix(patternTransform()->baseVal()->consolidate()->matrix()->qmatrix());

    if(refServer && refServer->type() == PS_PATTERN)
    {
        KRenderingPaintServerPattern *refPattern = static_cast<KRenderingPaintServerPattern *>(refServer);
        
        if(!hasAttribute(KDOM::DOMString("patternUnits").handle()))
        {
            KDOM::DOMString value(target->getAttribute(KDOM::DOMString("patternUnits").handle()));
            if(value == "userSpaceOnUse")
                patternUnits()->setBaseVal(SVG_UNIT_TYPE_USERSPACEONUSE);
            else if(value == "objectBoundingBox")
                patternUnits()->setBaseVal(SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
        }
        
        if(!hasAttribute(KDOM::DOMString("patternContentUnits").handle()))
        {
            KDOM::DOMString value(target->getAttribute(KDOM::DOMString("patternContentUnits").handle()));
            if(value == "userSpaceOnUse")
                patternContentUnits()->setBaseVal(SVG_UNIT_TYPE_USERSPACEONUSE);
            else if(value == "objectBoundingBox")
                patternContentUnits()->setBaseVal(SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
        }

        if(!hasAttribute(KDOM::DOMString("patternTransform").handle()))
            patternTransformMatrix = refPattern->patternTransform();
    }

    SVGStyledElementImpl *activeElement = static_cast<SVGStyledElementImpl *>(m_paintServer->activeClient()->userData());

    bool bbox = (patternUnits()->baseVal() == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);

    const SVGStyledElementImpl *savedContext = 0;
    if(bbox)
    {
        if(width()->baseVal()->unitType() != SVG_LENGTHTYPE_PERCENTAGE)
            width()->baseVal()->newValueSpecifiedUnits(SVG_LENGTHTYPE_PERCENTAGE, width()->baseVal()->value() * 100.);
        if(height()->baseVal()->unitType() != SVG_LENGTHTYPE_PERCENTAGE)
            height()->baseVal()->newValueSpecifiedUnits(SVG_LENGTHTYPE_PERCENTAGE, height()->baseVal()->value() * 100.);
        if(activeElement)
            savedContext = const_cast<SVGPatternElementImpl *>(this)->pushAttributeContext(activeElement);
    }    

    delete m_tile;
    m_tile = static_cast<KCanvasImage *>(canvas()->renderingDevice()->createResource(RS_IMAGE));
    m_tile->init(newSize);

    KRenderingDeviceContext *patternContext = canvas()->renderingDevice()->contextForImage(m_tile);
    canvas()->renderingDevice()->pushContext(patternContext);
//    KCanvasCommonArgs args;
//    args.setCanvas(canvas());
//    args.setStyle(item->style());
    
    KRenderingPaintServerPattern *pattern = static_cast<KRenderingPaintServerPattern *>(m_paintServer);
    pattern->setX(x()->baseVal()->value());
    pattern->setY(y()->baseVal()->value());
    pattern->setWidth(width()->baseVal()->value());
    pattern->setHeight(height()->baseVal()->value());
    pattern->setPatternTransform(patternTransformMatrix);
    pattern->setTile(m_tile);

    for(KDOM::NodeImpl *n = target->firstChild(); n != 0; n = n->nextSibling())
    {
        SVGStyledElementImpl *e = dynamic_cast<SVGStyledElementImpl *>(n);
        KCanvasItem *item = (e ? e->canvasItem() : 0);
        if(item && item->style())
        {
            KCanvasMatrix savedMatrix = item->style()->objectMatrix();

            const SVGStyledElementImpl *savedContext = 0;
            if(patternContentUnits()->baseVal() == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
            {
                if(activeElement)
                    savedContext = e->pushAttributeContext(activeElement);
            }

            // Take into account viewportElement's viewBox, if existant...
            if(viewportElement() && viewportElement()->id() == ID_SVG)
            {
                SVGSVGElementImpl *svgElement = static_cast<SVGSVGElementImpl *>(viewportElement());

                SVGMatrixImpl *svgCTM = svgElement->getCTM();
                svgCTM->ref();

                SVGMatrixImpl *ctm = SVGLocatableImpl::getCTM();
                ctm->ref();

                KCanvasMatrix newMatrix(svgCTM->qmatrix());
                newMatrix.multiply(savedMatrix);
                newMatrix.scale(1.0 / ctm->a(), 1.0 / ctm->d());

                item->style()->setObjectMatrix(newMatrix);

                ctm->deref();
                svgCTM->deref();
            }

            item->draw(QRect());

            if(savedContext)
                e->pushAttributeContext(savedContext);

            item->style()->setObjectMatrix(savedMatrix);
        }
    }

    if(savedContext)
        const_cast<SVGPatternElementImpl *>(this)->pushAttributeContext(savedContext);

    canvas()->renderingDevice()->popContext();
    delete patternContext;

    patternUnits()->setBaseVal(savedPatternUnits);
    patternContentUnits()->setBaseVal(savedPatternContentUnits);

    // Update all users of this resource...
    const KCanvasItemList &clients = pattern->clients();

    KCanvasItemList::ConstIterator it = clients.begin();
    KCanvasItemList::ConstIterator end = clients.end();

    for(; it != end; ++it)
    {
        const KCanvasItem *current = (*it);

        SVGStyledElementImpl *styled = (current ? static_cast<SVGStyledElementImpl *>(current->userData()) : 0);
        if(styled)
        {
            styled->setChanged(true);

            if(styled->canvasItem())
                styled->canvasItem()->invalidate();
        }
    }

    m_ignoreAttributeChanges = false;
}

KCanvasItem *SVGPatternElementImpl::createCanvasItem(KCanvas *canvas, KRenderingStyle *) const
{
    m_paintServer = canvas->renderingDevice()->createPaintServer(KCPaintServerType(PS_PATTERN));
    KRenderingPaintServerPattern *pserver = static_cast<KRenderingPaintServerPattern *>(m_paintServer);

    pserver->setListener(const_cast<SVGPatternElementImpl *>(this));

    canvas->registry()->addPaintServerById(KDOM::DOMString(getId()).string(), pserver);

    return 0;
}

SVGMatrixImpl *SVGPatternElementImpl::getCTM() const
{
    SVGMatrixImpl *mat = SVGSVGElementImpl::createSVGMatrix();
    if(mat)
    {
        SVGMatrixImpl *viewBox = viewBoxToViewTransform(width()->baseVal()->value(),
                                                        height()->baseVal()->value());

        viewBox->ref();
        mat->multiply(viewBox);
        viewBox->deref();
    }

    return mat;
}

// vim:ts=4:noet
