/*
 * Copyright (C) 2010 Alex Milowski (alex@milowski.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 "RenderMathMLSubSup.h"

#include "FontSelector.h"
#include "MathMLNames.h"
#include "RenderInline.h"
#include "RenderTable.h"
#include "RenderTableCell.h"
#include "RenderTableRow.h"
#include "RenderTableSection.h"
#include "RenderText.h"

namespace WebCore {
    
using namespace MathMLNames;

static const int gTopAdjustDivisor = 3;
static const int gSubsupScriptMargin = 1;
static const float gSubSupStretch = 1.2f;

RenderMathMLSubSup::RenderMathMLSubSup(Element* element) 
    : RenderMathMLBlock(element)
    , m_scripts(0)
{
    // Determine what kind of under/over expression we have by element name
    if (element->hasLocalName(MathMLNames::msubTag))
        m_kind = Sub;
    else if (element->hasLocalName(MathMLNames::msupTag))
        m_kind = Sup;
    else if (element->hasLocalName(MathMLNames::msubsupTag))
        m_kind = SubSup;
    else 
        m_kind = SubSup;
}

void RenderMathMLSubSup::addChild(RenderObject* child, RenderObject* beforeChild)
{
    if (firstChild()) {
        // We already have a base, so this is the super/subscripts being added.
        
        if (m_kind == SubSup) {
            if (!m_scripts) {
                m_scripts = new (renderArena()) RenderMathMLBlock(node());
                RefPtr<RenderStyle> scriptsStyle = RenderStyle::create();
                scriptsStyle->inheritFrom(style());
                scriptsStyle->setDisplay(INLINE_BLOCK);
                scriptsStyle->setVerticalAlign(TOP);
                scriptsStyle->setMarginLeft(Length(gSubsupScriptMargin, Fixed));
                scriptsStyle->setTextAlign(LEFT);
                m_scripts->setStyle(scriptsStyle.release());
                RenderMathMLBlock::addChild(m_scripts, beforeChild);
            }
            
            RenderBlock* script = new (renderArena()) RenderMathMLBlock(node());
            RefPtr<RenderStyle> scriptStyle = RenderStyle::create();
            scriptStyle->inheritFrom(m_scripts->style());
            scriptStyle->setDisplay(BLOCK);
            script->setStyle(scriptStyle.release());
            
            m_scripts->addChild(script, m_scripts->firstChild());
            script->addChild(child);
        } else
            RenderMathMLBlock::addChild(child, beforeChild);
        
    } else {
        RenderMathMLBlock* wrapper = new (renderArena()) RenderMathMLBlock(node());
        RefPtr<RenderStyle> wrapperStyle = RenderStyle::create();
        wrapperStyle->inheritFrom(style());
        wrapperStyle->setDisplay(INLINE_BLOCK);
        wrapperStyle->setVerticalAlign(BASELINE);
        wrapper->setStyle(wrapperStyle.release());
        RenderMathMLBlock::addChild(wrapper, beforeChild);
        wrapper->addChild(child);
        
    }
}

void RenderMathMLSubSup::stretchToHeight(int height)
{
    RenderObject* base = firstChild();
    if (!base)
        return;
    
    if (base->firstChild()->isRenderMathMLBlock()) {
        RenderMathMLBlock* block = toRenderMathMLBlock(base->firstChild());
        block->stretchToHeight(static_cast<int>(gSubSupStretch * height));
        
        // Adjust the script placement after we stretch
        if (height > 0 && m_kind == SubSup && m_scripts) {
            RenderObject* script = m_scripts->firstChild();
            if (script) {
                // Calculate the script height without the container margins.
                RenderObject* top = script;
                int topHeight = getBoxModelObjectHeight(top->firstChild());
                int topAdjust = topHeight / gTopAdjustDivisor;
                top->style()->setMarginTop(Length(-topAdjust, Fixed));
                top->style()->setMarginBottom(Length(height - topHeight + topAdjust, Fixed));
                if (top->isBoxModelObject()) {
                    RenderBoxModelObject* topBox = toRenderBoxModelObject(top);
                    topBox->updateBoxModelInfoFromStyle();
                }
                m_scripts->setNeedsLayout(true);
                setNeedsLayout(true);
            }
        }
        
    }
}

int RenderMathMLSubSup::nonOperatorHeight() const 
{
    if (m_kind == SubSup) 
       return static_cast<int>(style()->fontSize()*gSubSupStretch);
    return static_cast<int>(style()->fontSize());
}

void RenderMathMLSubSup::layout() 
{
    if (firstChild())
        firstChild()->setNeedsLayout(true);
    if (m_scripts) 
        m_scripts->setNeedsLayout(true);
    
    RenderBlock::layout();
    
    if (m_kind == SubSup) {
        if (RenderObject* base = firstChild()) {
            int maxHeight = 0;
            RenderObject* current = base->firstChild();
            while (current) {
                int height = getBoxModelObjectHeight(current);
                if (height > maxHeight)
                    maxHeight = height;
                current = current->nextSibling();
            }
            int heightDiff = m_scripts ? (m_scripts->offsetHeight() - maxHeight) / 2 : 0;
            if (heightDiff < 0) 
                heightDiff = 0;
            base->style()->setPaddingTop(Length(heightDiff, Fixed));
            base->setNeedsLayout(true);
        }
        setNeedsLayout(true);
        RenderBlock::layout();
    }    
}

int RenderMathMLSubSup::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
{
    RenderObject* base = firstChild();
    if (!base) 
        return offsetHeight();
    
    int baseline = offsetHeight();
    if (!base || !base->isBoxModelObject()) 
        return baseline;

    switch (m_kind) {
    case SubSup:
        base = base->firstChild();
        if (m_scripts && base->isBoxModelObject()) {
            RenderBoxModelObject* box = toRenderBoxModelObject(base);
            
            int topAdjust = (m_scripts->offsetHeight() - box->offsetHeight()) / 2;
        
            // FIXME: The last bit of this calculation should be more exact.  Why is the 2-3px scaled for zoom necessary?
            // The baseline is top spacing of the base + the baseline of the base + adjusted space for zoom
            float zoomFactor = style()->effectiveZoom();
            return topAdjust + box->baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode) + static_cast<int>((zoomFactor > 1.25 ? 2 : 3) * zoomFactor);
        }
        break;
    case Sup: 
    case Sub:
        RenderBoxModelObject* box = toRenderBoxModelObject(base);
        baseline = box->baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode);
        break;
    }
    
    return baseline;
    
}
    
}    

#endif // ENABLE(MATHML)
