/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 * Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2004, 2006, 2009, 2010 Apple Inc. All rights reserved.
 *
 * 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "RenderWidget.h"

#include "AXObjectCache.h"
#include "AnimationController.h"
#include "GraphicsContext.h"
#include "HitTestResult.h"
#include "RenderCounter.h"
#include "RenderLayer.h"
#include "RenderView.h"
#include "RenderWidgetProtector.h"

#if USE(ACCELERATED_COMPOSITING)
#include "RenderLayerBacking.h"
#endif

using namespace std;

namespace WebCore {

static HashMap<const Widget*, RenderWidget*>& widgetRendererMap()
{
    static HashMap<const Widget*, RenderWidget*>* staticWidgetRendererMap = new HashMap<const Widget*, RenderWidget*>;
    return *staticWidgetRendererMap;
}

static size_t widgetHierarchyUpdateSuspendCount;

typedef HashMap<RefPtr<Widget>, FrameView*> WidgetToParentMap;

static WidgetToParentMap& widgetNewParentMap()
{
    DEFINE_STATIC_LOCAL(WidgetToParentMap, map, ());
    return map;
}

void RenderWidget::suspendWidgetHierarchyUpdates()
{
    widgetHierarchyUpdateSuspendCount++;
}

void RenderWidget::resumeWidgetHierarchyUpdates()
{
    ASSERT(widgetHierarchyUpdateSuspendCount);
    if (widgetHierarchyUpdateSuspendCount == 1) {
        WidgetToParentMap map = widgetNewParentMap();
        widgetNewParentMap().clear();
        WidgetToParentMap::iterator end = map.end();
        for (WidgetToParentMap::iterator it = map.begin(); it != end; ++it) {
            Widget* child = it->first.get();
            ScrollView* currentParent = child->parent();
            FrameView* newParent = it->second;
            if (newParent != currentParent) {
                if (currentParent)
                    currentParent->removeChild(child);
                if (newParent)
                    newParent->addChild(child);
            }
        }
    }
    widgetHierarchyUpdateSuspendCount--;
}

static void moveWidgetToParentSoon(Widget* child, FrameView* parent)
{
    if (!widgetHierarchyUpdateSuspendCount) {
        if (parent)
            parent->addChild(child);
        else
            child->removeFromParent();
        return;
    }
    widgetNewParentMap().set(child, parent);
}

RenderWidget::RenderWidget(Node* node)
    : RenderReplaced(node)
    , m_widget(0)
    , m_frameView(node->document()->view())
    // Reference counting is used to prevent the widget from being
    // destroyed while inside the Widget code, which might not be
    // able to handle that.
    , m_refCount(1)
{
    view()->addWidget(this);
}

void RenderWidget::destroy()
{
    // We can't call the base class's destroy because we don't
    // want to unconditionally delete ourselves (we're ref-counted).
    // So the code below includes copied and pasted contents of
    // both RenderBox::destroy() and RenderObject::destroy().
    // Fix originally made for <rdar://problem/4228818>.

    animation()->cancelAnimations(this);

    if (RenderView* v = view())
        v->removeWidget(this);

    
    if (AXObjectCache::accessibilityEnabled()) {
        document()->axObjectCache()->childrenChanged(this->parent());
        document()->axObjectCache()->remove(this);
    }

    if (!documentBeingDestroyed() && parent()) 
        parent()->dirtyLinesFromChangedChild(this);

    remove();

    if (m_hasCounterNodeMap)
        RenderCounter::destroyCounterNodes(this);

    setWidget(0);

    // removes from override size map
    if (hasOverrideSize())
        setOverrideSize(-1);

    if (style() && (style()->logicalHeight().isPercent() || style()->logicalMinHeight().isPercent() || style()->logicalMaxHeight().isPercent()))
        RenderBlock::removePercentHeightDescendant(this);

    if (hasLayer()) {
        layer()->clearClipRects();
        setHasLayer(false);
        destroyLayer();
    }

    // Grab the arena from node()->document()->renderArena() before clearing the node pointer.
    // Clear the node before deref-ing, as this may be deleted when deref is called.
    RenderArena* arena = renderArena();
    setNode(0);
    deref(arena);
}

RenderWidget::~RenderWidget()
{
    ASSERT(m_refCount <= 0);
    clearWidget();
}

bool RenderWidget::setWidgetGeometry(const IntRect& frame, const IntSize& boundsSize)
{
    if (!node())
        return false;

    IntRect clipRect = enclosingLayer()->childrenClipRect();
    bool clipChanged = m_clipRect != clipRect;
    bool boundsChanged = m_widget->frameRect() != frame;

    if (!boundsChanged && !clipChanged)
        return false;

    m_clipRect = clipRect;

    RenderWidgetProtector protector(this);
    RefPtr<Node> protectedNode(node());
    m_widget->setFrameRect(frame);
    if (m_widget) // setFrameRect can run arbitrary script, which might clear m_widget.
        m_widget->setBoundsSize(boundsSize);
    
#if USE(ACCELERATED_COMPOSITING)
    if (hasLayer() && layer()->isComposited())
        layer()->backing()->updateAfterWidgetResize();
#endif
    
    return boundsChanged;
}

void RenderWidget::setWidget(PassRefPtr<Widget> widget)
{
    if (widget == m_widget)
        return;

    if (m_widget) {
        moveWidgetToParentSoon(m_widget.get(), 0);
        widgetRendererMap().remove(m_widget.get());
        clearWidget();
    }
    m_widget = widget;
    if (m_widget) {
        widgetRendererMap().add(m_widget.get(), this);
        // If we've already received a layout, apply the calculated space to the
        // widget immediately, but we have to have really been fully constructed (with a non-null
        // style pointer).
        if (style()) {
            if (!needsLayout())
                setWidgetGeometry(IntRect(localToAbsoluteQuad(FloatQuad(contentBoxRect())).boundingBox()), contentBoxRect().size());
            if (style()->visibility() != VISIBLE)
                m_widget->hide();
            else {
                m_widget->show();
                repaint();
            }
        }
        moveWidgetToParentSoon(m_widget.get(), m_frameView);
    }
}

void RenderWidget::layout()
{
    ASSERT(needsLayout());

    setNeedsLayout(false);
}

void RenderWidget::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    RenderReplaced::styleDidChange(diff, oldStyle);
    if (m_widget) {
        if (style()->visibility() != VISIBLE)
            m_widget->hide();
        else
            m_widget->show();
    }
}

void RenderWidget::showSubstituteImage(PassRefPtr<Image> prpImage)
{
    m_substituteImage = prpImage;
    repaint();
}

void RenderWidget::notifyWidget(WidgetNotification notification)
{
    if (m_widget)
        m_widget->notifyWidget(notification);
}

void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty)
{
    if (!shouldPaint(paintInfo, tx, ty))
        return;

    tx += x();
    ty += y();

    if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))
        paintBoxDecorations(paintInfo, tx, ty);

    if (paintInfo.phase == PaintPhaseMask) {
        paintMask(paintInfo, tx, ty);
        return;
    }

    if (!m_frameView || paintInfo.phase != PaintPhaseForeground || style()->visibility() != VISIBLE)
        return;

#if PLATFORM(MAC)
    if (style()->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
        paintCustomHighlight(tx - x(), ty - y(), style()->highlight(), true);
#endif

    if (style()->hasBorderRadius()) {
        IntRect borderRect = IntRect(tx, ty, width(), height());

        if (borderRect.isEmpty())
            return;

        // Push a clip if we have a border radius, since we want to round the foreground content that gets painted.
        paintInfo.context->save();
        paintInfo.context->addRoundedRectClip(style()->getRoundedBorderFor(borderRect));
    }

    if (m_widget) {
        // Tell the widget to paint now.  This is the only time the widget is allowed
        // to paint itself.  That way it will composite properly with z-indexed layers.
        if (m_substituteImage)
            paintInfo.context->drawImage(m_substituteImage.get(), style()->colorSpace(), m_widget->frameRect());
        else {
            IntPoint widgetLocation = m_widget->frameRect().location();
            IntPoint paintLocation(tx + borderLeft() + paddingLeft(), ty + borderTop() + paddingTop());
            IntRect paintRect = paintInfo.rect;

            IntSize paintOffset = paintLocation - widgetLocation;
            // When painting widgets into compositing layers, tx and ty are relative to the enclosing compositing layer,
            // not the root. In this case, shift the CTM and adjust the paintRect to be root-relative to fix plug-in drawing.
            if (!paintOffset.isZero()) {
                paintInfo.context->translate(paintOffset);
                paintRect.move(-paintOffset);
            }
            m_widget->paint(paintInfo.context, paintRect);

            if (!paintOffset.isZero())
                paintInfo.context->translate(-paintOffset);
        }

        if (m_widget->isFrameView()) {
            FrameView* frameView = static_cast<FrameView*>(m_widget.get());
            bool runOverlapTests = !frameView->useSlowRepaintsIfNotOverlapped() || frameView->hasCompositedContentIncludingDescendants();
            if (paintInfo.overlapTestRequests && runOverlapTests) {
                ASSERT(!paintInfo.overlapTestRequests->contains(this));
                paintInfo.overlapTestRequests->set(this, m_widget->frameRect());
            }
         }
    }

    if (style()->hasBorderRadius())
        paintInfo.context->restore();

    // Paint a partially transparent wash over selected widgets.
    if (isSelected() && !document()->printing()) {
        // FIXME: selectionRect() is in absolute, not painting coordinates.
        paintInfo.context->fillRect(selectionRect(), selectionBackgroundColor(), style()->colorSpace());
    }
}

void RenderWidget::setOverlapTestResult(bool isOverlapped)
{
    ASSERT(m_widget);
    ASSERT(m_widget->isFrameView());
    static_cast<FrameView*>(m_widget.get())->setIsOverlapped(isOverlapped);
}

void RenderWidget::deref(RenderArena *arena)
{
    if (--m_refCount <= 0)
        arenaDelete(arena, this);
}

void RenderWidget::updateWidgetPosition()
{
    if (!m_widget || !node()) // Check the node in case destroy() has been called.
        return;

    IntRect contentBox = contentBoxRect();
    IntRect absoluteContentBox = IntRect(localToAbsoluteQuad(FloatQuad(contentBox)).boundingBox());
    bool boundsChanged = setWidgetGeometry(absoluteContentBox, contentBox.size());

    // if the frame bounds got changed, or if view needs layout (possibly indicating
    // content size is wrong) we have to do a layout to set the right widget size
    if (m_widget && m_widget->isFrameView()) {
        FrameView* frameView = static_cast<FrameView*>(m_widget.get());
        // Check the frame's page to make sure that the frame isn't in the process of being destroyed.
        if ((boundsChanged || frameView->needsLayout()) && frameView->frame()->page())
            frameView->layout();
    }
}

void RenderWidget::widgetPositionsUpdated()
{
    if (!m_widget)
        return;
    m_widget->widgetPositionsUpdated();
}

IntRect RenderWidget::windowClipRect() const
{
    if (!m_frameView)
        return IntRect();

    return intersection(m_frameView->contentsToWindow(m_clipRect), m_frameView->windowClipRect());
}

void RenderWidget::setSelectionState(SelectionState state)
{
    if (selectionState() != state) {
        RenderReplaced::setSelectionState(state);
        if (m_widget)
            m_widget->setIsSelected(isSelected());
    }
}

void RenderWidget::clearWidget()
{
    m_widget = 0;
}

RenderWidget* RenderWidget::find(const Widget* widget)
{
    return widgetRendererMap().get(widget);
}

bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction action)
{
    bool hadResult = result.innerNode();
    bool inside = RenderReplaced::nodeAtPoint(request, result, x, y, tx, ty, action);
    
    // Check to see if we are really over the widget itself (and not just in the border/padding area).
    if ((inside || result.isRectBasedTest()) && !hadResult && result.innerNode() == node())
        result.setIsOverWidget(contentBoxRect().contains(result.localPoint()));
    return inside;
}

} // namespace WebCore
