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

#include "FontCascade.h"
#include "Hyphenation.h"
#include "RenderBlockFlow.h"
#include "RenderChildIterator.h"
#include "SimpleLineLayoutFlowContents.h"

namespace WebCore {
namespace SimpleLineLayout {

TextFragmentIterator::Style::Style(const RenderStyle& style, bool useSimplifiedTextMeasuring)
    : font(style.fontCascade())
    , textAlign(style.textAlign())
    , hasKerningOrLigatures(font.enableKerning() || font.requiresShaping())
    , collapseWhitespace(style.collapseWhiteSpace())
    , preserveNewline(style.preserveNewline())
    , wrapLines(style.autoWrap())
    , breakAnyWordOnOverflow(style.wordBreak() == BreakAllWordBreak && wrapLines)
    , breakFirstWordOnOverflow(breakAnyWordOnOverflow || (style.breakWords() && (wrapLines || preserveNewline)))
    , breakNBSP(wrapLines && style.nbspMode() == SPACE)
    , keepAllWordsForCJK(style.wordBreak() == KeepAllWordBreak)
    , wordSpacing(font.wordSpacing())
    , tabWidth(collapseWhitespace ? 0 : style.tabSize())
    , shouldHyphenate(style.hyphens() == HyphensAuto && canHyphenate(style.locale()))
    , hyphenStringWidth(shouldHyphenate ? (useSimplifiedTextMeasuring ? font.widthForSimpleText(style.hyphenString()) : font.width(TextRun(style.hyphenString()))) : 0)
    , hyphenLimitBefore(style.hyphenationLimitBefore() < 0 ? 2 : style.hyphenationLimitBefore())
    , hyphenLimitAfter(style.hyphenationLimitAfter() < 0 ? 2 : style.hyphenationLimitAfter())
    , locale(style.locale())
{
    if (style.hyphenationLimitLines() > -1)
        hyphenLimitLines = style.hyphenationLimitLines();
}

TextFragmentIterator::TextFragmentIterator(const RenderBlockFlow& flow)
    : m_flowContents(flow)
    , m_currentSegment(m_flowContents.begin())
    , m_lineBreakIterator(m_currentSegment->text, flow.style().locale())
    , m_style(flow.style(), m_currentSegment->canUseSimplifiedTextMeasuring)
{
}

TextFragmentIterator::TextFragment TextFragmentIterator::nextTextFragment(float xPosition)
{
    TextFragmentIterator::TextFragment nextFragment = findNextTextFragment(xPosition);
    m_atEndOfSegment = (m_currentSegment == m_flowContents.end()) || (m_position == m_currentSegment->end);
    return nextFragment;
}

TextFragmentIterator::TextFragment TextFragmentIterator::findNextTextFragment(float xPosition)
{
    // A fragment can either be
    // 1. line break when <br> is present or preserveNewline is on (not considered as whitespace) or
    // 2. whitespace (collasped, non-collapsed multi or single) or
    // 3. non-whitespace characters.
    // 4. content end.
    ASSERT(m_currentSegment != m_flowContents.end());
    unsigned startPosition = m_position;
    if (m_atEndOfSegment)
        ++m_currentSegment;

    if (m_currentSegment == m_flowContents.end())
        return TextFragment(startPosition, startPosition, 0, TextFragment::ContentEnd);
    if (isHardLineBreak(m_currentSegment))
        return TextFragment(startPosition, startPosition, 0, TextFragment::HardLineBreak);
    if (isSoftLineBreak(startPosition)) {
        unsigned endPosition = ++m_position;
        return TextFragment(startPosition, endPosition, 0, TextFragment::SoftLineBreak);
    }
    float width = 0;
    bool overlappingFragment = false;
    unsigned endPosition = skipToNextPosition(PositionType::NonWhitespace, startPosition, width, xPosition, overlappingFragment);
    unsigned segmentEndPosition = m_currentSegment->end;
    ASSERT(startPosition <= endPosition);
    if (startPosition < endPosition) {
        bool multipleWhitespace = startPosition + 1 < endPosition;
        bool isCollapsed = multipleWhitespace && m_style.collapseWhitespace;
        m_position = endPosition;
        return TextFragment(startPosition, endPosition, width, TextFragment::Whitespace, endPosition == segmentEndPosition, false, isCollapsed, m_style.collapseWhitespace);
    }
    endPosition = skipToNextPosition(PositionType::Breakable, startPosition, width, xPosition, overlappingFragment);
    m_position = endPosition;
    return TextFragment(startPosition, endPosition, width, TextFragment::NonWhitespace, endPosition == segmentEndPosition, overlappingFragment, false, false);
}

void TextFragmentIterator::revertToEndOfFragment(const TextFragment& fragment)
{
    ASSERT(m_position >= fragment.end());
    while (m_currentSegment->start > fragment.end())
        --m_currentSegment;
    // TODO: It reverts to the last fragment on the same position, but that's ok for now as we don't need to
    // differentiate multiple renderers on the same position.
    m_position = fragment.end();
    m_atEndOfSegment = false;
}

static inline unsigned nextBreakablePositionInSegment(LazyLineBreakIterator& lineBreakIterator, unsigned startPosition, bool breakNBSP, bool keepAllWordsForCJK)
{
    if (keepAllWordsForCJK) {
        if (breakNBSP)
            return nextBreakablePositionKeepingAllWords(lineBreakIterator, startPosition);
        return nextBreakablePositionKeepingAllWordsIgnoringNBSP(lineBreakIterator, startPosition);
    }

    if (lineBreakIterator.mode() == LineBreakIteratorMode::Default) {
        if (breakNBSP)
            return WebCore::nextBreakablePosition(lineBreakIterator, startPosition);
        return nextBreakablePositionIgnoringNBSP(lineBreakIterator, startPosition);
    }

    if (breakNBSP)
        return nextBreakablePositionWithoutShortcut(lineBreakIterator, startPosition);
    return nextBreakablePositionIgnoringNBSPWithoutShortcut(lineBreakIterator, startPosition);
}

unsigned TextFragmentIterator::nextBreakablePosition(const FlowContents::Segment& segment, unsigned startPosition)
{
    ASSERT(startPosition < segment.end);
    StringView currentText = m_lineBreakIterator.stringView();
    StringView segmentText = StringView(segment.text);
    if (segmentText != currentText) {
        unsigned textLength = currentText.length();
        UChar lastCharacter = textLength > 0 ? currentText[textLength - 1] : 0;
        UChar secondToLastCharacter = textLength > 1 ? currentText[textLength - 2] : 0;
        m_lineBreakIterator.setPriorContext(lastCharacter, secondToLastCharacter);
        m_lineBreakIterator.resetStringAndReleaseIterator(segment.text, m_style.locale, LineBreakIteratorMode::Default);
    }
    return segment.toRenderPosition(nextBreakablePositionInSegment(m_lineBreakIterator, segment.toSegmentPosition(startPosition), m_style.breakNBSP, m_style.keepAllWordsForCJK));
}

unsigned TextFragmentIterator::nextNonWhitespacePosition(const FlowContents::Segment& segment, unsigned startPosition)
{
    ASSERT(startPosition < segment.end);
    unsigned position = startPosition;
    for (; position < segment.end; ++position) {
        auto character = segment.text[segment.toSegmentPosition(position)];
        bool isWhitespace = character == ' ' || character == '\t' || (!m_style.preserveNewline && character == '\n');
        if (!isWhitespace)
            return position;
    }
    return position;
}

std::optional<unsigned> TextFragmentIterator::lastHyphenPosition(const TextFragmentIterator::TextFragment& run, unsigned before) const
{
    ASSERT(run.start() < before);
    auto& segment = *m_currentSegment;
    ASSERT(segment.start <= before && before <= segment.end);
    ASSERT(is<RenderText>(segment.renderer));
    if (!m_style.shouldHyphenate || run.type() != TextFragment::NonWhitespace)
        return std::nullopt;
    // Check if there are enough characters in the run.
    unsigned runLength = run.end() - run.start();
    if (m_style.hyphenLimitBefore >= runLength || m_style.hyphenLimitAfter >= runLength || m_style.hyphenLimitBefore + m_style.hyphenLimitAfter > runLength)
        return std::nullopt;
    auto runStart = segment.toSegmentPosition(run.start());
    auto beforeIndex = segment.toSegmentPosition(before) - runStart;
    if (beforeIndex <= m_style.hyphenLimitBefore)
        return std::nullopt;
    // Adjust before index to accommodate the limit-after value (this is the last potential hyphen location).
    beforeIndex = std::min(beforeIndex, runLength - m_style.hyphenLimitAfter + 1);
    auto substringForHyphenation = StringView(segment.text).substring(runStart, run.end() - run.start());
    auto hyphenLocation = lastHyphenLocation(substringForHyphenation, beforeIndex, m_style.locale);
    // Check if there are enough characters before and after the hyphen.
    if (hyphenLocation && hyphenLocation >= m_style.hyphenLimitBefore && m_style.hyphenLimitAfter <= (runLength - hyphenLocation))
        return segment.toRenderPosition(hyphenLocation + runStart);
    return std::nullopt;
}

unsigned TextFragmentIterator::skipToNextPosition(PositionType positionType, unsigned startPosition, float& width, float xPosition, bool& overlappingFragment)
{
    overlappingFragment = false;
    unsigned currentPosition = startPosition;
    unsigned nextPosition = currentPosition;
    // Collapsed whitespace has constant width. Do not measure it.
    if (positionType == NonWhitespace)
        nextPosition = nextNonWhitespacePosition(*m_currentSegment, currentPosition);
    else if (positionType == Breakable) {
        nextPosition = nextBreakablePosition(*m_currentSegment, currentPosition);
        // nextBreakablePosition returns the same position for certain characters such as hyphens. Call next again with modified position unless we are at the end of the segment.
        bool skipCurrentPosition = nextPosition == currentPosition;
        if (skipCurrentPosition) {
            // When we are skipping the last character in the segment, just move to the end of the segment and we'll check the next segment whether it is an overlapping fragment.
            ASSERT(currentPosition < m_currentSegment->end);
            if (currentPosition == m_currentSegment->end - 1)
                nextPosition = m_currentSegment->end;
            else
                nextPosition = nextBreakablePosition(*m_currentSegment, currentPosition + 1);
        }
        // We need to know whether the word actually finishes at the end of this renderer or not.
        if (nextPosition == m_currentSegment->end) {
            const auto nextSegment = m_currentSegment + 1;
            if (nextSegment != m_flowContents.end() && !isHardLineBreak(nextSegment))
                overlappingFragment = nextPosition < nextBreakablePosition(*nextSegment, nextPosition);
        }
    }
    width = 0;
    if (nextPosition == currentPosition)
        return currentPosition;
    // Both non-collapsed whitespace and non-whitespace runs need to be measured.
    bool measureText = positionType != NonWhitespace || !m_style.collapseWhitespace;
    if (measureText)
        width = this->textWidth(currentPosition, nextPosition, xPosition);
    else if (startPosition < nextPosition)
        width = m_style.font.spaceWidth() + m_style.wordSpacing;
    return nextPosition;
}

float TextFragmentIterator::textWidth(unsigned from, unsigned to, float xPosition) const
{
    auto& segment = *m_currentSegment;
    ASSERT(segment.start <= from && from <= segment.end && segment.start <= to && to <= segment.end);
    ASSERT(is<RenderText>(segment.renderer));
    if (!m_style.font.size() || from == to)
        return 0;

    unsigned segmentFrom = segment.toSegmentPosition(from);
    unsigned segmentTo = segment.toSegmentPosition(to);
    if (m_style.font.isFixedPitch())
        return downcast<RenderText>(segment.renderer).width(segmentFrom, segmentTo - segmentFrom, m_style.font, xPosition, nullptr, nullptr);

    bool measureWithEndSpace = m_style.hasKerningOrLigatures && m_style.collapseWhitespace
        && segmentTo < segment.text.length() && segment.text[segmentTo] == ' ';
    if (measureWithEndSpace)
        ++segmentTo;
    float width = 0;
    if (segment.canUseSimplifiedTextMeasuring)
        width = m_style.font.widthForSimpleText(StringView(segment.text).substring(segmentFrom, segmentTo - segmentFrom));
    else {
        TextRun run(StringView(segment.text).substring(segmentFrom, segmentTo - segmentFrom), xPosition);
        if (m_style.tabWidth)
            run.setTabSize(true, m_style.tabWidth);
        width = m_style.font.width(run);
    }
    if (measureWithEndSpace)
        width -= (m_style.font.spaceWidth() + m_style.wordSpacing);
    return std::max<float>(0, width);
}

}
}
