/*
 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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"
#include "TextAutoSizing.h"

#if ENABLE(TEXT_AUTOSIZING)

#include "CSSFontSelector.h"
#include "Document.h"
#include "FontCascade.h"
#include "Logging.h"
#include "RenderBlock.h"
#include "RenderListMarker.h"
#include "RenderText.h"
#include "RenderTextFragment.h"
#include "RenderTreeBuilder.h"
#include "Settings.h"
#include "StyleResolver.h"

namespace WebCore {

static RenderStyle cloneRenderStyleWithState(const RenderStyle& currentStyle)
{
    auto newStyle = RenderStyle::clone(currentStyle);

    // FIXME: This should probably handle at least ::first-line too.
    if (auto* firstLetterStyle = currentStyle.getCachedPseudoStyle(PseudoId::FirstLetter))
        newStyle.addCachedPseudoStyle(makeUnique<RenderStyle>(RenderStyle::clone(*firstLetterStyle)));

    if (currentStyle.lastChildState())
        newStyle.setLastChildState();
    if (currentStyle.firstChildState())
        newStyle.setFirstChildState();
    return newStyle;
}

TextAutoSizingKey::TextAutoSizingKey(DeletedTag)
{
    HashTraits<std::unique_ptr<RenderStyle>>::constructDeletedValue(m_style);
}

TextAutoSizingKey::TextAutoSizingKey(const RenderStyle& style, unsigned hash)
    : m_style(RenderStyle::clonePtr(style)) // FIXME: This seems very inefficient.
    , m_hash(hash)
{
}

void TextAutoSizingValue::addTextNode(Text& node, float size)
{
    node.renderer()->setCandidateComputedTextSize(size);
    m_autoSizedNodes.add(&node);
}

auto TextAutoSizingValue::adjustTextNodeSizes() -> StillHasNodes
{
    // Remove stale nodes. Nodes may have had their renderers detached. We'll also need to remove the style from the documents m_textAutoSizedNodes
    // collection. Return true indicates we need to do that removal.
    Vector<Text*> nodesForRemoval;
    for (auto& textNode : m_autoSizedNodes) {
        auto* renderer = textNode->renderer();
        if (!renderer || !renderer->style().textSizeAdjust().isAuto() || !renderer->candidateComputedTextSize())
            nodesForRemoval.append(textNode.get());
    }

    for (auto& node : nodesForRemoval)
        m_autoSizedNodes.remove(node);

    StillHasNodes stillHasNodes = m_autoSizedNodes.isEmpty() ? StillHasNodes::No : StillHasNodes::Yes;

    // If we only have one piece of text with the style on the page don't adjust it's size.
    if (m_autoSizedNodes.size() <= 1)
        return stillHasNodes;

    // Compute average size.
    float cumulativeSize = 0;
    for (auto& node : m_autoSizedNodes)
        cumulativeSize += node->renderer()->candidateComputedTextSize();

    float averageSize = std::round(cumulativeSize / m_autoSizedNodes.size());

    // FIXME: Figure out how to make this code use RenderTreeUpdater/Builder properly.
    RenderTreeBuilder builder((*m_autoSizedNodes.begin())->renderer()->view());

    // Adjust sizes.
    bool firstPass = true;
    for (auto& node : m_autoSizedNodes) {
        auto& renderer = *node->renderer();
        if (renderer.style().fontDescription().computedSize() == averageSize)
            continue;

        float specifiedSize = renderer.style().fontDescription().specifiedSize();
        float maxScaleIncrease = renderer.settings().maxTextAutosizingScaleIncrease();
        float scaleChange = averageSize / specifiedSize;
        if (scaleChange > maxScaleIncrease && firstPass) {
            firstPass = false;
            averageSize = std::round(specifiedSize * maxScaleIncrease);
            scaleChange = averageSize / specifiedSize;
        }

        LOG(TextAutosizing, "  adjust node size %p firstPass=%d averageSize=%f scaleChange=%f", node.get(), firstPass, averageSize, scaleChange);

        auto* parentRenderer = renderer.parent();

        auto style = cloneRenderStyleWithState(renderer.style());
        auto fontDescription = style.fontDescription();
        fontDescription.setComputedSize(averageSize);
        style.setFontDescription(FontCascadeDescription { fontDescription });
        style.fontCascade().update(&node->document().fontSelector());
        parentRenderer->setStyle(WTFMove(style));

        if (parentRenderer->isAnonymousBlock())
            parentRenderer = parentRenderer->parent();

        // If we have a list we should resize ListMarkers separately.
        if (is<RenderListMarker>(*parentRenderer->firstChild())) {
            auto& listMarkerRenderer = downcast<RenderListMarker>(*parentRenderer->firstChild());
            auto style = cloneRenderStyleWithState(listMarkerRenderer.style());
            style.setFontDescription(FontCascadeDescription { fontDescription });
            style.fontCascade().update(&node->document().fontSelector());
            listMarkerRenderer.setStyle(WTFMove(style));
        }

        // Resize the line height of the parent.
        auto& parentStyle = parentRenderer->style();
        auto& lineHeightLength = parentStyle.specifiedLineHeight();

        int specifiedLineHeight;
        if (lineHeightLength.isPercent())
            specifiedLineHeight = minimumValueForLength(lineHeightLength, fontDescription.specifiedSize());
        else
            specifiedLineHeight = lineHeightLength.value();

        // This calculation matches the line-height computed size calculation in StyleBuilderCustom::applyValueLineHeight().
        int lineHeight = specifiedLineHeight * scaleChange;
        if (lineHeightLength.isFixed() && lineHeightLength.value() == lineHeight)
            continue;

        auto newParentStyle = cloneRenderStyleWithState(parentStyle);
        newParentStyle.setLineHeight(lineHeightLength.isNegative() ? Length(lineHeightLength) : Length(lineHeight, LengthType::Fixed));
        newParentStyle.setSpecifiedLineHeight(Length { lineHeightLength });
        newParentStyle.setFontDescription(WTFMove(fontDescription));
        newParentStyle.fontCascade().update(&node->document().fontSelector());
        parentRenderer->setStyle(WTFMove(newParentStyle));

        builder.updateAfterDescendants(*parentRenderer);
    }

    for (auto& node : m_autoSizedNodes) {
        auto& textRenderer = *node->renderer();
        if (!is<RenderTextFragment>(textRenderer))
            continue;
        auto* block = downcast<RenderTextFragment>(textRenderer).blockForAccompanyingFirstLetter();
        if (!block)
            continue;

        RenderObject* firstLetterRenderer;
        RenderElement* dummy;
        block->getFirstLetter(firstLetterRenderer, dummy);
        if (firstLetterRenderer && firstLetterRenderer->parent() && firstLetterRenderer->parent()->parent()) {
            auto& parentStyle = firstLetterRenderer->parent()->parent()->style();
            auto* firstLetterStyle = parentStyle.getCachedPseudoStyle(PseudoId::FirstLetter);
            if (!firstLetterStyle)
                continue;
            auto fontDescription = firstLetterStyle->fontDescription();
            fontDescription.setComputedSize(averageSize * fontDescription.specifiedSize() / parentStyle.fontDescription().specifiedSize());
            firstLetterStyle->setFontDescription(FontCascadeDescription { fontDescription });
            firstLetterStyle->fontCascade().update(&node->document().fontSelector());
        }

        builder.updateAfterDescendants(*block);
    }

    return stillHasNodes;
}

TextAutoSizingValue::~TextAutoSizingValue()
{
    reset();
}

void TextAutoSizingValue::reset()
{
    for (auto& node : m_autoSizedNodes) {
        auto* renderer = node->renderer();
        if (!renderer)
            continue;

        auto* parentRenderer = renderer->parent();
        if (!parentRenderer)
            continue;

        // Reset the font size back to the original specified size
        auto fontDescription = renderer->style().fontDescription();
        float originalSize = fontDescription.specifiedSize();
        if (fontDescription.computedSize() != originalSize) {
            fontDescription.setComputedSize(originalSize);
            auto style = cloneRenderStyleWithState(renderer->style());
            style.setFontDescription(FontCascadeDescription { fontDescription });
            style.fontCascade().update(&node->document().fontSelector());
            parentRenderer->setStyle(WTFMove(style));
        }

        // Reset the line height of the parent.
        if (parentRenderer->isAnonymousBlock())
            parentRenderer = parentRenderer->parent();

        auto& parentStyle = parentRenderer->style();
        auto& originalLineHeight = parentStyle.specifiedLineHeight();
        if (originalLineHeight == parentStyle.lineHeight())
            continue;

        auto newParentStyle = cloneRenderStyleWithState(parentStyle);
        newParentStyle.setLineHeight(Length { originalLineHeight });
        newParentStyle.setFontDescription(WTFMove(fontDescription));
        newParentStyle.fontCascade().update(&node->document().fontSelector());
        parentRenderer->setStyle(WTFMove(newParentStyle));
    }
}

void TextAutoSizing::addTextNode(Text& node, float candidateSize)
{
    LOG(TextAutosizing, " addAutoSizedNode %p candidateSize=%f", &node, candidateSize);
    auto addResult = m_textNodes.add<TextAutoSizingHashTranslator>(node.renderer()->style(), nullptr);
    if (addResult.isNewEntry)
        addResult.iterator->value = makeUnique<TextAutoSizingValue>();
    addResult.iterator->value->addTextNode(node, candidateSize);
}

void TextAutoSizing::updateRenderTree()
{
    m_textNodes.removeIf([](auto& keyAndValue) {
        return keyAndValue.value->adjustTextNodeSizes() == TextAutoSizingValue::StillHasNodes::No;
    });
}

void TextAutoSizing::reset()
{
    m_textNodes.clear();
}

} // namespace WebCore

#endif // ENABLE(TEXT_AUTOSIZING)
