/*
 * Copyright (C) 2006 Eric Seidel (eric@webkit.org)
 *
 * 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. OR
 * CONTRIBUTORS 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. 
 */

#include "config.h"
#if ENABLE(SVG)

#include "CachedPage.h"
#include "DocumentLoader.h"
#include "EditCommand.h"
#include "FloatRect.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "ImageObserver.h"
#include "NotImplemented.h"
#include "Page.h"
#include "ResourceError.h"
#include "SVGDocument.h"
#include "SVGImage.h"
#include "SVGLength.h"
#include "SVGSVGElement.h"

#include "SVGImageEmptyClients.h"

namespace WebCore {

SVGImage::SVGImage(ImageObserver* observer)
    : Image(observer)
    , m_document(0)
    , m_page(0)
    , m_frame(0)
    , m_frameView(0)
{
}

SVGImage::~SVGImage()
{
    if (m_frame)
        m_frame->loader()->frameDetached(); // Break both the loader and view references to the frame
}

IntSize SVGImage::size() const
{
    IntSize defaultSize(300, 150);
    // FIXME: Eventually we'll be passed in the dest size and can scale against that
    IntSize destSize = defaultSize;
    
    if (!m_frame || !m_frame->document())
        return IntSize();
    
    SVGSVGElement* rootElement = static_cast<SVGDocument*>(m_frame->document())->rootElement();
    if (!rootElement)
        return defaultSize;
    
    SVGLength width = rootElement->width();
    SVGLength height = rootElement->height();
    
    IntSize svgSize;
    if (width.unitType() == LengthTypePercentage)
        svgSize.setWidth(static_cast<int>(width.valueInSpecifiedUnits() * destSize.width()));
    else
        svgSize.setWidth(static_cast<int>(width.value()));
    if (height.unitType() == LengthTypePercentage)
        svgSize.setHeight(static_cast<int>(height.valueInSpecifiedUnits() * destSize.height()));
    else
        svgSize.setHeight(static_cast<int>(height.value()));
    
    return svgSize;
}

void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp)
{
    if (!m_frame)
        return;
    
    context->save();
    context->clip(enclosingIntRect(dstRect));
    context->translate(dstRect.location().x(), dstRect.location().y());
    context->scale(FloatSize(dstRect.width()/srcRect.width(), dstRect.height()/srcRect.height()));
    m_frame->paint(context, enclosingIntRect(srcRect));
    context->restore();

    if (imageObserver())
        imageObserver()->didDraw(this);
}

NativeImagePtr SVGImage::nativeImageForCurrentFrame()
{
    // FIXME: In order to support dynamic SVGs we need to have a way to invalidate this
    // frame cache, or better yet, not use a cache for tiled drawing at all, instead
    // having a tiled drawing callback (hopefully non-virtual).
    if (!m_frameCache) {
        m_frameCache.set(ImageBuffer::create(size(), false).release());
        ImageBuffer::renderSubtreeToImage(m_frameCache.get(), m_frame->renderer());
    }
#if PLATFORM(CG)
    return m_frameCache->cgImage();
#elif PLATFORM(QT)
    return m_frameCache->pixmap();
#elif PLATFORM(CAIRO)
    return m_frameCache->surface();
#else
    notImplemented();
    return 0;
#endif
}

bool SVGImage::dataChanged(bool allDataReceived)
{
    int length = m_data->size();
    if (!length) // if this was an empty image
        return true;
    
    if (allDataReceived) {
        static ChromeClient* dummyChromeClient = new SVGEmptyChromeClient;
        static FrameLoaderClient* dummyFrameLoaderClient =  new SVGEmptyFrameLoaderClient;
        static EditorClient* dummyEditorClient = new SVGEmptyEditorClient;
        static ContextMenuClient* dummyContextMenuClient = new SVGEmptyContextMenuClient;
        static DragClient* dummyDragClient = new SVGEmptyDragClient;
        static InspectorClient* dummyInspectorClient = new SVGEmptyInspectorClient;

        // FIXME: If this SVG ends up loading itself, we'll leak this Frame (and associated DOM & render trees).
        // The Cache code does not know about CachedImages holding Frames and won't know to break the cycle.
        m_page.set(new Page(dummyChromeClient, dummyContextMenuClient, dummyEditorClient, dummyDragClient, dummyInspectorClient));
        m_frame = new Frame(m_page.get(), 0, dummyFrameLoaderClient);
        m_frame->init();
        m_frameView = new FrameView(m_frame.get());
        m_frameView->deref(); // FIXME: FrameView starts with a refcount of 1
        m_frame->setView(m_frameView.get());
        ResourceRequest fakeRequest(KURL(""));
        m_frame->loader()->load(fakeRequest); // Make sure the DocumentLoader is created
        m_frame->loader()->cancelContentPolicyCheck(); // cancel any policy checks
        m_frame->loader()->commitProvisionalLoad(0);
        m_frame->loader()->setResponseMIMEType("image/svg+xml");
        m_frame->loader()->begin("placeholder.svg"); // create the empty document
        m_frame->loader()->write(m_data->data(), m_data->size());
        m_frame->loader()->end();
    }
    return m_frameView;
}

}

#endif // ENABLE(SVG)
