/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2000 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
 *
 * 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 "RenderFieldset.h"

#include "CSSPropertyNames.h"
#include "GraphicsContext.h"
#include "HTMLNames.h"
#include "PaintInfo.h"

#if ENABLE(WML)
#include "WMLNames.h"
#endif

using std::min;
using std::max;

namespace WebCore {

using namespace HTMLNames;

RenderFieldset::RenderFieldset(Node* element)
    : RenderBlock(element)
{
}

void RenderFieldset::computePreferredLogicalWidths()
{
    RenderBlock::computePreferredLogicalWidths();
    if (RenderBox* legend = findLegend()) {
        int legendMinWidth = legend->minPreferredLogicalWidth();

        Length legendMarginLeft = legend->style()->marginLeft();
        Length legendMarginRight = legend->style()->marginLeft();

        if (legendMarginLeft.isFixed())
            legendMinWidth += legendMarginLeft.value();

        if (legendMarginRight.isFixed())
            legendMinWidth += legendMarginRight.value();

        m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, legendMinWidth + borderAndPaddingWidth());
    }
}

RenderObject* RenderFieldset::layoutSpecialExcludedChild(bool relayoutChildren)
{
    RenderBox* legend = findLegend();
    if (legend) {
        if (relayoutChildren)
            legend->setNeedsLayout(true);
        legend->layoutIfNeeded();

        int logicalLeft;
        if (style()->isLeftToRightDirection()) {
            switch (legend->style()->textAlign()) {
            case CENTER:
                logicalLeft = (logicalWidth() - logicalWidthForChild(legend)) / 2;
                break;
            case RIGHT:
                logicalLeft = logicalWidth() - borderEnd() - paddingEnd() - logicalWidthForChild(legend);
                break;
            default:
                logicalLeft = borderStart() + paddingStart() + marginStartForChild(legend);
                break;
            }
        } else {
            switch (legend->style()->textAlign()) {
            case LEFT:
                logicalLeft = borderStart() + paddingStart();
                break;
            case CENTER: {
                // Make sure that the extra pixel goes to the end side in RTL (since it went to the end side
                // in LTR).
                int centeredWidth = logicalWidth() - logicalWidthForChild(legend);
                logicalLeft = centeredWidth - centeredWidth / 2;
                break;
            }
            default:
                logicalLeft = logicalWidth() - borderStart() - paddingStart() - marginStartForChild(legend) - logicalWidthForChild(legend);
                break;
            }
        }

        setLogicalLeftForChild(legend, logicalLeft);

        int b = borderBefore();
        int h = logicalHeightForChild(legend);
        setLogicalTopForChild(legend, max((b - h) / 2, 0));
        setLogicalHeight(max(b, h) + paddingBefore());
    }
    return legend;
}

RenderBox* RenderFieldset::findLegend() const
{
    for (RenderObject* legend = firstChild(); legend; legend = legend->nextSibling()) {
        if (!legend->isFloatingOrPositioned() && legend->node() &&
            (legend->node()->hasTagName(legendTag)
#if ENABLE(WML)
            || legend->node()->hasTagName(WMLNames::insertedLegendTag)
#endif
            )
           )
            return toRenderBox(legend);
    }
    return 0;
}

void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
{
    if (!paintInfo.shouldPaintWithinRoot(this))
        return;

    int w = width();
    int h = height();
    RenderBox* legend = findLegend();
    if (!legend)
        return RenderBlock::paintBoxDecorations(paintInfo, tx, ty);

    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
    // cases the legend is embedded in the right and bottom borders respectively.
    // https://bugs.webkit.org/show_bug.cgi?id=47236
    if (style()->isHorizontalWritingMode()) {
        int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2;
        h -= yOff;
        ty += yOff;
    } else {
        int xOff = (legend->x() > 0) ? 0 : (legend->width() - borderLeft()) / 2;
        w -= xOff;
        tx += xOff;
    }

    paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal);

    paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), tx, ty, w, h);
    paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset);

    if (!style()->hasBorder())
        return;
    
    // Create a clipping region around the legend and paint the border as normal
    GraphicsContext* graphicsContext = paintInfo.context;
    graphicsContext->save();

    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
    // cases the legend is embedded in the right and bottom borders respectively.
    // https://bugs.webkit.org/show_bug.cgi?id=47236
    if (style()->isHorizontalWritingMode()) {
        int clipTop = ty;
        int clipHeight = max(static_cast<int>(style()->borderTopWidth()), legend->height());
        graphicsContext->clipOut(IntRect(tx + legend->x(), clipTop, legend->width(), clipHeight));
    } else {
        int clipLeft = tx;
        int clipWidth = max(static_cast<int>(style()->borderLeftWidth()), legend->width());
        graphicsContext->clipOut(IntRect(clipLeft, ty + legend->y(), clipWidth, legend->height()));
    }

    paintBorder(paintInfo.context, tx, ty, w, h, style(), true, true);

    graphicsContext->restore();
}

void RenderFieldset::paintMask(PaintInfo& paintInfo, int tx, int ty)
{
    if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
        return;

    int w = width();
    int h = height();
    RenderBox* legend = findLegend();
    if (!legend)
        return RenderBlock::paintMask(paintInfo, tx, ty);

    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
    // cases the legend is embedded in the right and bottom borders respectively.
    // https://bugs.webkit.org/show_bug.cgi?id=47236
    if (style()->isHorizontalWritingMode()) {
        int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2;
        h -= yOff;
        ty += yOff;
    } else {
        int xOff = (legend->x() > 0) ? 0 : (legend->width() - borderLeft()) / 2;
        w -= xOff;
        tx += xOff;
    }

    paintMaskImages(paintInfo, tx, ty, w, h);
}

} // namespace WebCore
