/*
 * Copyright (C) 2019 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 "LineLayoutContext.h"

#if ENABLE(LAYOUT_FORMATTING_CONTEXT)

#include "InlineLineBreaker.h"
#include "LayoutBox.h"
#include "TextUtil.h"

namespace WebCore {
namespace Layout {

static LayoutUnit inlineItemWidth(const FormattingContext& formattingContext, const InlineItem& inlineItem, LayoutUnit contentLogicalLeft)
{
    if (inlineItem.isForcedLineBreak())
        return { };

    if (is<InlineTextItem>(inlineItem)) {
        auto& inlineTextItem = downcast<InlineTextItem>(inlineItem);
        auto contentWidth = inlineTextItem.width();
        if (!contentWidth) {
            auto end = inlineTextItem.isCollapsible() ? inlineTextItem.start() + 1 : inlineTextItem.end();
            contentWidth = TextUtil::width(inlineTextItem.layoutBox(), inlineTextItem.start(), end, contentLogicalLeft);
        }
        auto wordSpacing = inlineTextItem.isWhitespace() ? LayoutUnit(inlineTextItem.style().fontCascade().wordSpacing()) : 0_lu;
        return *contentWidth + wordSpacing;
    }

    auto& layoutBox = inlineItem.layoutBox();
    auto& boxGeometry = formattingContext.geometryForBox(layoutBox);

    if (layoutBox.isFloatingPositioned())
        return boxGeometry.marginBoxWidth();

    if (layoutBox.replaced())
        return boxGeometry.width();

    if (inlineItem.isContainerStart())
        return boxGeometry.marginStart() + boxGeometry.borderLeft() + boxGeometry.paddingLeft().valueOr(0);

    if (inlineItem.isContainerEnd())
        return boxGeometry.marginEnd() + boxGeometry.borderRight() + boxGeometry.paddingRight().valueOr(0);

    // Non-replaced inline box (e.g. inline-block)
    return boxGeometry.width();
}

LineLayoutContext::LineLayoutContext(const InlineFormattingContext& inlineFormattingContext, const Container& formattingContextRoot, const InlineItems& inlineItems)
    : m_inlineFormattingContext(inlineFormattingContext)
    , m_formattingContextRoot(formattingContextRoot)
    , m_inlineItems(inlineItems)
{
}

LineLayoutContext::LineContent LineLayoutContext::layoutLine(LineBuilder& line, unsigned leadingInlineItemIndex, Optional<PartialContent> leadingPartialContent)
{
    auto initialize = [&] {
        m_committedInlineItemCount = 0;
        m_uncommittedContent.reset();
        m_leadingPartialTextItem = { };
        m_trailingPartialTextItem = { };
        m_overflowPartialContent = { };
    };
    initialize();
    // Iterate through the inline content and place the inline boxes on the current line.
    // Start with the partial leading text from the previous line.
    auto firstNonPartialInlineItemIndex = leadingInlineItemIndex;
    if (leadingPartialContent) {
        // Handle partial inline item (split text from the previous line).
        auto& leadingTextItem = m_inlineItems[leadingInlineItemIndex];
        RELEASE_ASSERT(leadingTextItem->isText());
        // Construct a partial leading inline item.
        ASSERT(!m_leadingPartialTextItem);
        m_leadingPartialTextItem = downcast<InlineTextItem>(*leadingTextItem).right(leadingPartialContent->length);
        if (placeInlineItem(line, *m_leadingPartialTextItem) == IsEndOfLine::Yes)
            return close(line, leadingInlineItemIndex);
        ++firstNonPartialInlineItemIndex;
    }

    for (auto inlineItemIndex = firstNonPartialInlineItemIndex; inlineItemIndex < m_inlineItems.size(); ++inlineItemIndex) {
        // FIXME: We should not need to re-measure the dropped, uncommitted content when re-using them on the next line.
        if (placeInlineItem(line, *m_inlineItems[inlineItemIndex]) == IsEndOfLine::Yes)
            return close(line, leadingInlineItemIndex);
    }
    // Check the uncommitted content whether they fit now that we know we are at a commit boundary.
    if (!m_uncommittedContent.isEmpty())
        processUncommittedContent(line);
    return close(line, leadingInlineItemIndex);
}

void LineLayoutContext::commitPendingContent(LineBuilder& line)
{
    if (m_uncommittedContent.isEmpty())
        return;
    m_committedInlineItemCount += m_uncommittedContent.size();
    for (auto& uncommittedRun : m_uncommittedContent.runs())
        line.append(uncommittedRun.inlineItem, uncommittedRun.logicalWidth);
    m_uncommittedContent.reset();
}

LineLayoutContext::LineContent LineLayoutContext::close(LineBuilder& line, unsigned leadingInlineItemIndex)
{
    ASSERT(m_committedInlineItemCount || line.hasIntrusiveFloat());
    m_uncommittedContent.reset();
    if (!m_committedInlineItemCount)
        return LineContent { { }, { }, WTFMove(m_floats), line.close(), line.lineBox() };

    auto trailingInlineItemIndex = leadingInlineItemIndex + m_committedInlineItemCount - 1;
    auto isLastLineWithInlineContent = [&] {
        if (m_overflowPartialContent)
            return LineBuilder::IsLastLineWithInlineContent::No;
        // Skip floats backwards to see if this is going to be the last line with inline content.
        for (auto i = m_inlineItems.size(); i--;) {
            if (!m_inlineItems[i]->isFloat())
                return i == trailingInlineItemIndex ? LineBuilder::IsLastLineWithInlineContent::Yes : LineBuilder::IsLastLineWithInlineContent::No;
        }
        // There has to be at least one non-float item.
        ASSERT_NOT_REACHED();
        return LineBuilder::IsLastLineWithInlineContent::No;
    };

    return LineContent { trailingInlineItemIndex, m_overflowPartialContent, WTFMove(m_floats), line.close(isLastLineWithInlineContent()), line.lineBox() };
}

LineLayoutContext::IsEndOfLine LineLayoutContext::placeInlineItem(LineBuilder& line, const InlineItem& inlineItem)
{
    auto currentLogicalRight = line.lineBox().logicalRight();
    auto itemLogicalWidth = inlineItemWidth(formattingContext(), inlineItem, currentLogicalRight);

    // Floats are special, they are intrusive but they don't really participate in the line layout context.
    if (inlineItem.isFloat()) {
        // FIXME: It gets a bit more complicated when there's some uncommitted content whether they should be added to the current line
        // e.g. text_content<div style="float: left"></div>continuous_text_content
        // Not sure what to do when the float takes up the available space and we've got continuous content. Browser engines don't agree.
        // Let's just commit the pending content and try placing the float for now.
        if (!m_uncommittedContent.isEmpty()) {
            if (processUncommittedContent(line) == IsEndOfLine::Yes)
                return IsEndOfLine::Yes;
        }
        auto lineIsConsideredEmpty = line.isVisuallyEmpty() && !line.hasIntrusiveFloat();
        if (LineBreaker().shouldWrapFloatBox(itemLogicalWidth, line.availableWidth() + line.trailingTrimmableWidth(), lineIsConsideredEmpty))
            return IsEndOfLine::Yes;

        // This float can sit on the current line.
        auto& floatBox = inlineItem.layoutBox();
        // Shrink available space for current line and move existing inline runs.
        floatBox.isLeftFloatingPositioned() ? line.moveLogicalLeft(itemLogicalWidth) : line.moveLogicalRight(itemLogicalWidth);
        m_floats.append(makeWeakPtr(inlineItem));
        ++m_committedInlineItemCount;
        line.setHasIntrusiveFloat();
        return IsEndOfLine::No;
    }
    // Forced line breaks are also special.
    if (inlineItem.isForcedLineBreak()) {
        auto isEndOfLine = !m_uncommittedContent.isEmpty() ? processUncommittedContent(line) : IsEndOfLine::No;
        // When the uncommitted content fits(or the line is empty), add the line break to this line as well.
        if (isEndOfLine == IsEndOfLine::No) {
            m_uncommittedContent.append(inlineItem, itemLogicalWidth);
            commitPendingContent(line);
        }
        return IsEndOfLine::Yes;
    }
    //
    auto isEndOfLine = IsEndOfLine::No;
    // Can we commit the pending content already?
    if (LineBreaker::Content::isAtContentBoundary(inlineItem, m_uncommittedContent))
        isEndOfLine = processUncommittedContent(line);
    // The current item might fit as well.
    if (isEndOfLine == IsEndOfLine::No)
        m_uncommittedContent.append(inlineItem, itemLogicalWidth);
    return isEndOfLine;
}

LineLayoutContext::IsEndOfLine LineLayoutContext::processUncommittedContent(LineBuilder& line)
{
    auto shouldDisableHyphenation = [&] {
        auto& style = m_formattingContextRoot.style();
        unsigned limitLines = style.hyphenationLimitLines() == RenderStyle::initialHyphenationLimitLines() ? std::numeric_limits<unsigned>::max() : style.hyphenationLimitLines();
        return m_successiveHyphenatedLineCount >= limitLines;
    };

    // Check if the pending content fits.
    auto lineIsConsideredEmpty = line.isVisuallyEmpty() && !line.hasIntrusiveFloat();
    auto lineBreaker = LineBreaker { };
    if (shouldDisableHyphenation())
        lineBreaker.setHyphenationDisabled();
    auto lineStatus = LineBreaker::LineStatus { line.availableWidth(), line.trailingTrimmableWidth(), line.isTrailingRunFullyTrimmable(), lineIsConsideredEmpty };
    auto breakingContext = lineBreaker.breakingContextForInlineContent(m_uncommittedContent, lineStatus);
    // The uncommitted content can fully, partially fit the current line (commit/partial commit) or not at all (reset).
    if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Keep)
        commitPendingContent(line);
    else if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Split) {
        ASSERT(breakingContext.trailingPartialContent);
        ASSERT(m_uncommittedContent.runs()[breakingContext.trailingPartialContent->runIndex].inlineItem.isText());
        // Turn the uncommitted trailing run into a partial trailing run.
        auto overflowInlineTextItemIndex = breakingContext.trailingPartialContent->runIndex;
        auto& overflowInlineTextItem = downcast<InlineTextItem>(m_uncommittedContent.runs()[overflowInlineTextItemIndex].inlineItem);

        // Construct a partial trailing inline run.
        ASSERT(!m_trailingPartialTextItem);
        auto trailingContentLength = breakingContext.trailingPartialContent->length;
        m_trailingPartialTextItem = overflowInlineTextItem.left(trailingContentLength);
        m_overflowPartialContent = PartialContent { overflowInlineTextItem.length() - trailingContentLength };
        // Keep the non-overflow part of the uncommitted runs and add the trailing partial content.
        m_uncommittedContent.trim(overflowInlineTextItemIndex);
        m_uncommittedContent.append(*m_trailingPartialTextItem, breakingContext.trailingPartialContent->logicalWidth);
        commitPendingContent(line);
    } else if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Wrap)
        m_uncommittedContent.reset();
    else
        ASSERT_NOT_REACHED();
    // Adjust hyphenated line count
    m_successiveHyphenatedLineCount = breakingContext.trailingPartialContent && breakingContext.trailingPartialContent->hasHyphen ? m_successiveHyphenatedLineCount + 1 : 0;
    return breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Keep ? IsEndOfLine::No :IsEndOfLine::Yes;
}

}
}

#endif
