/*
 * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved.
 * Copyright (C) 2010 François Sausset (sausset@gmail.com). All rights reserved.
 *
 * 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 THE COPYRIGHT
 * OWNER 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(MATHML)

#include "RenderMathMLRoot.h"

#include "FontCache.h"
#include "GraphicsContext.h"
#include "PaintInfo.h"
#include "RenderIterator.h"
#include "RenderMathMLRadicalOperator.h"
#include "RenderMathMLSquareRoot.h"

namespace WebCore {
    
// RenderMathMLRoot implements drawing of radicals via the <mroot> and <msqrt> elements. For valid MathML elements, the DOM is
//
// <mroot> Base Index </mroot>
// <msqrt> Child1 Child2 ... ChildN </msqrt>
//
// and the structure of the render tree will be
//
// IndexWrapper RadicalWrapper BaseWrapper
//
// where RadicalWrapper contains an <mo>&#x221A;</mo>.
// For <mroot>, the IndexWrapper and BaseWrapper should contain exactly one child (Index and Base respectively).
// For <msqrt>, the IndexWrapper should be empty and the BaseWrapper can contain any number of children (Child1, ... ChildN).
//
// In order to accept invalid markup and to handle <mroot> and <msqrt> consistently, we will allow any number of children in the BaseWrapper of <mroot> too.
// We will allow the IndexWrapper to be empty and it will always contain the last child of the <mroot> if there are at least 2 elements.

RenderMathMLRoot::RenderMathMLRoot(Element& element, std::unique_ptr<RenderStyle> style)
    : RenderMathMLBlock(element, WTFMove(style))
{
}

RenderMathMLRoot::RenderMathMLRoot(Document& document, std::unique_ptr<RenderStyle> style)
    : RenderMathMLBlock(document, WTFMove(style))
{
}

RenderMathMLRootWrapper* RenderMathMLRoot::baseWrapper() const
{
    ASSERT(!isEmpty());
    return downcast<RenderMathMLRootWrapper>(lastChild());
}

RenderMathMLBlock* RenderMathMLRoot::radicalWrapper() const
{
    ASSERT(!isEmpty());
    return downcast<RenderMathMLBlock>(lastChild()->previousSibling());
}

RenderMathMLRootWrapper* RenderMathMLRoot::indexWrapper() const
{
    ASSERT(!isEmpty());
    return is<RenderMathMLSquareRoot>(*this) ? nullptr : downcast<RenderMathMLRootWrapper>(firstChild());
}

RenderMathMLRadicalOperator* RenderMathMLRoot::radicalOperator() const
{
    ASSERT(!isEmpty());
    return downcast<RenderMathMLRadicalOperator>(radicalWrapper()->firstChild());
}

void RenderMathMLRoot::restructureWrappers()
{
    ASSERT(!isEmpty());

    auto base = baseWrapper();
    auto index = indexWrapper();
    auto radical = radicalWrapper();

    // For visual consistency with the initial state, we remove the radical when the base/index wrappers become empty.
    if (base->isEmpty() && (!index || index->isEmpty())) {
        if (!radical->isEmpty()) {
            auto child = radicalOperator();
            radical->removeChild(*child);
            child->destroy();
        }
        // FIXME: early return!!!
    }

    if (radical->isEmpty()) {
        // We create the radical operator.
        RenderPtr<RenderMathMLRadicalOperator> radicalOperator = createRenderer<RenderMathMLRadicalOperator>(document(), RenderStyle::createAnonymousStyleWithDisplay(&style(), FLEX));
        radicalOperator->initializeStyle();
        radical->addChild(radicalOperator.leakPtr());
    }

    if (isRenderMathMLSquareRoot())
        return;

    if (auto childToMove = base->lastChild()) {
        // We move the last child of the base wrapper into the index wrapper if the index wrapper is empty and the base wrapper has at least two children.
        if (childToMove->previousSibling() && index->isEmpty()) {
            base->removeChildWithoutRestructuring(*childToMove);
            index->addChild(childToMove);
        }
    }

    if (auto childToMove = index->firstChild()) {
        // We move the first child of the index wrapper into the base wrapper if:
        // - either the index wrapper has at least two children.
        // - or the base wrapper is empty but the index wrapper is not.
        if (childToMove->nextSibling() || base->isEmpty()) {
            index->removeChildWithoutRestructuring(*childToMove);
            base->addChild(childToMove);
        }
    }
}

void RenderMathMLRoot::addChild(RenderObject* newChild, RenderObject* beforeChild)
{
    if (isEmpty()) {
        if (!isRenderMathMLSquareRoot()) {
            // We add the IndexWrapper.
            RenderMathMLBlock::addChild(RenderMathMLRootWrapper::createAnonymousWrapper(this).leakPtr());
        }

        // We create the radicalWrapper
        RenderMathMLBlock::addChild(RenderMathMLBlock::createAnonymousMathMLBlock().leakPtr());

        // We create the BaseWrapper.
        RenderMathMLBlock::addChild(RenderMathMLRootWrapper::createAnonymousWrapper(this).leakPtr());

        updateStyle();
    }

    // We insert the child.
    auto base = baseWrapper();
    auto index = indexWrapper();
    RenderElement* actualParent;
    RenderElement* actualBeforeChild;
    if (is<RenderMathMLSquareRoot>(*this)) {
        // For square root, we always insert the child into the base wrapper.
        actualParent = base;
        if (beforeChild && beforeChild->parent() == base)
            actualBeforeChild = downcast<RenderElement>(beforeChild);
        else
            actualBeforeChild = nullptr;
    } else {
        // For mroot, we insert the child into the parent of beforeChild, or at the end of the index. The wrapper structure is reorganize below.
        actualParent = beforeChild ? beforeChild->parent() : nullptr;
        if (actualParent == base || actualParent == index)
            actualBeforeChild = downcast<RenderElement>(beforeChild);
        else {
            actualParent = index;
            actualBeforeChild = nullptr;
        }
    }
    actualParent->addChild(newChild, actualBeforeChild);
    restructureWrappers();
}

void RenderMathMLRoot::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    RenderMathMLBlock::styleDidChange(diff, oldStyle);
    if (!isEmpty())
        updateStyle();
}

void RenderMathMLRoot::updateFromElement()
{
    RenderMathMLBlock::updateFromElement();
    if (!isEmpty())
        updateStyle();
}

void RenderMathMLRoot::updateStyle()
{
    ASSERT(!isEmpty());

    // We set some constants to draw the radical, as defined in the OpenType MATH tables.

    m_ruleThickness = 0.05f * style().fontCascade().size();

    // FIXME: The recommended default for m_verticalGap in displaystyle is rule thickness + 1/4 x-height (https://bugs.webkit.org/show_bug.cgi?id=118737).
    m_verticalGap = 11 * m_ruleThickness / 4;
    m_extraAscender = m_ruleThickness;
    LayoutUnit kernBeforeDegree = 5 * style().fontCascade().size() / 18;
    LayoutUnit kernAfterDegree = -10 * style().fontCascade().size() / 18;
    m_degreeBottomRaisePercent = 0.6f;

    const auto& primaryFont = style().fontCascade().primaryFont();
    if (auto* mathData = style().fontCascade().primaryFont().mathData()) {
        // FIXME: m_verticalGap should use RadicalDisplayStyleVertical in display mode (https://bugs.webkit.org/show_bug.cgi?id=118737).
        m_verticalGap = mathData->getMathConstant(primaryFont, OpenTypeMathData::RadicalVerticalGap);
        m_ruleThickness = mathData->getMathConstant(primaryFont, OpenTypeMathData::RadicalRuleThickness);
        m_extraAscender = mathData->getMathConstant(primaryFont, OpenTypeMathData::RadicalExtraAscender);

        if (!isRenderMathMLSquareRoot()) {
            kernBeforeDegree = mathData->getMathConstant(primaryFont, OpenTypeMathData::RadicalKernBeforeDegree);
            kernAfterDegree = mathData->getMathConstant(primaryFont, OpenTypeMathData::RadicalKernAfterDegree);
            m_degreeBottomRaisePercent = mathData->getMathConstant(primaryFont, OpenTypeMathData::RadicalDegreeBottomRaisePercent);
        }
    }

    // We set the style of the anonymous wrappers.

    auto radical = radicalWrapper();
    auto radicalStyle = RenderStyle::createAnonymousStyleWithDisplay(&style(), FLEX);
    radicalStyle->setMarginTop(Length(0, Fixed)); // This will be updated in RenderMathMLRoot::layout().
    radical->setStyle(WTFMove(radicalStyle));
    radical->setNeedsLayoutAndPrefWidthsRecalc();

    auto base = baseWrapper();
    auto baseStyle = RenderStyle::createAnonymousStyleWithDisplay(&style(), FLEX);
    baseStyle->setMarginTop(Length(0, Fixed)); // This will be updated in RenderMathMLRoot::layout().
    baseStyle->setAlignItemsPosition(ItemPositionBaseline);
    base->setStyle(WTFMove(baseStyle));
    base->setNeedsLayoutAndPrefWidthsRecalc();

    if (!isRenderMathMLSquareRoot()) {
        // For mroot, we also set the style of the index wrapper.
        auto index = indexWrapper();
        auto indexStyle = RenderStyle::createAnonymousStyleWithDisplay(&style(), FLEX);
        indexStyle->setMarginTop(Length(0, Fixed)); // This will be updated in RenderMathMLRoot::layout().
        indexStyle->setMarginStart(Length(kernBeforeDegree, Fixed));
        indexStyle->setMarginEnd(Length(kernAfterDegree, Fixed));
        indexStyle->setAlignItemsPosition(ItemPositionBaseline);
        index->setStyle(WTFMove(indexStyle));
        index->setNeedsLayoutAndPrefWidthsRecalc();
    }
}

Optional<int> RenderMathMLRoot::firstLineBaseline() const
{
    if (!isEmpty()) {
        auto base = baseWrapper();
        return static_cast<int>(lroundf(base->firstLineBaseline().valueOr(-1) + base->marginTop()));
    }

    return RenderMathMLBlock::firstLineBaseline();
}

void RenderMathMLRoot::layout()
{
    if (isEmpty()) {
        RenderMathMLBlock::layout();
        return;
    }

    // FIXME: It seems that changing the top margin of the base below modifies its logical height and leads to reftest failures.
    // For now, we workaround that by avoiding to recompute the child margins if they were not reset in updateStyle().
    auto base = baseWrapper();
    if (base->marginTop() > 0) {
        RenderMathMLBlock::layout();
        return;
    }

    // We layout the children.
    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
        if (child->needsLayout())
            downcast<RenderElement>(*child).layout();
    }

    auto radical = radicalOperator();
    if (radical) {
        // We stretch the radical sign to cover the height of the base wrapper.
        float baseHeight = base->logicalHeight();
        float baseHeightAboveBaseline = base->firstLineBaseline().valueOr(baseHeight);
        float baseDepthBelowBaseline = baseHeight - baseHeightAboveBaseline;
        baseHeightAboveBaseline += m_verticalGap;
        radical->stretchTo(baseHeightAboveBaseline, baseDepthBelowBaseline);

        // We modify the top margins to adjust the vertical positions of wrappers.
        float radicalTopMargin = m_extraAscender;
        float baseTopMargin = m_verticalGap + m_ruleThickness + m_extraAscender;
        if (!isRenderMathMLSquareRoot()) {
            // For mroot, we try to place the index so the space below its baseline is m_degreeBottomRaisePercent times the height of the radical.
            auto index = indexWrapper();
            float indexHeight = 0;
            if (!index->isEmpty())
                indexHeight = downcast<RenderBlock>(*index->firstChild()).logicalHeight();
            float indexTopMargin = (1.0 - m_degreeBottomRaisePercent) * radical->stretchSize() + radicalTopMargin - indexHeight;
            if (indexTopMargin < 0) {
                // If the index is too tall, we must add space at the top of renderer.
                radicalTopMargin -= indexTopMargin;
                baseTopMargin -= indexTopMargin;
                indexTopMargin = 0;
            }
            index->style().setMarginTop(Length(indexTopMargin, Fixed));
        }
        radical->style().setMarginTop(Length(radicalTopMargin, Fixed));
        base->style().setMarginTop(Length(baseTopMargin, Fixed));
    }

    RenderMathMLBlock::layout();
}

void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset)
{
    RenderMathMLBlock::paint(info, paintOffset);
    
    if (isEmpty() || info.context().paintingDisabled() || style().visibility() != VISIBLE)
        return;

    auto base = baseWrapper();
    auto radical = radicalOperator();
    if (!base || !radical || !m_ruleThickness)
        return;

    // We draw the radical line.
    GraphicsContextStateSaver stateSaver(info.context());

    info.context().setStrokeThickness(m_ruleThickness);
    info.context().setStrokeStyle(SolidStroke);
    info.context().setStrokeColor(style().visitedDependentColor(CSSPropertyColor));

    // The preferred width of the radical is sometimes incorrect, so we draw a slightly longer line to ensure it touches the radical symbol (https://bugs.webkit.org/show_bug.cgi?id=130326).
    LayoutUnit sizeError = radical->trailingSpaceError();
    IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location() + base->location() + LayoutPoint(-sizeError, -(m_verticalGap + m_ruleThickness / 2)));
    info.context().drawLine(adjustedPaintOffset, roundedIntPoint(LayoutPoint(adjustedPaintOffset.x() + base->offsetWidth() + sizeError, adjustedPaintOffset.y())));
}

RenderPtr<RenderMathMLRootWrapper> RenderMathMLRootWrapper::createAnonymousWrapper(RenderMathMLRoot* renderObject)
{
    RenderPtr<RenderMathMLRootWrapper> newBlock = createRenderer<RenderMathMLRootWrapper>(renderObject->document(), RenderStyle::createAnonymousStyleWithDisplay(&renderObject->style(), FLEX));
    newBlock->initializeStyle();
    return newBlock;
}

void RenderMathMLRootWrapper::removeChildWithoutRestructuring(RenderObject& child)
{
    RenderMathMLBlock::removeChild(child);
}

void RenderMathMLRootWrapper::removeChild(RenderObject& child)
{
    RenderMathMLBlock::removeChild(child);

    if (!(beingDestroyed() || documentBeingDestroyed()))
        downcast<RenderMathMLRoot>(*parent()).restructureWrappers();
}

}

#endif // ENABLE(MATHML)
