/*
 * Copyright (C) 2013 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * 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"
#include "core/rendering/AbstractInlineTextBox.h"

#include "core/editing/TextIterator.h"
#include "platform/text/TextBreakIterator.h"

namespace blink {

AbstractInlineTextBox::InlineToAbstractInlineTextBoxHashMap* AbstractInlineTextBox::gAbstractInlineTextBoxMap = 0;

PassRefPtr<AbstractInlineTextBox> AbstractInlineTextBox::getOrCreate(RenderText* renderText, InlineTextBox* inlineTextBox)
{
    if (!inlineTextBox)
        return nullptr;

    if (!gAbstractInlineTextBoxMap)
        gAbstractInlineTextBoxMap = new InlineToAbstractInlineTextBoxHashMap();

    InlineToAbstractInlineTextBoxHashMap::const_iterator it = gAbstractInlineTextBoxMap->find(inlineTextBox);
    if (it != gAbstractInlineTextBoxMap->end())
        return it->value;

    RefPtr<AbstractInlineTextBox> obj = adoptRef(new AbstractInlineTextBox(renderText, inlineTextBox));
    gAbstractInlineTextBoxMap->set(inlineTextBox, obj);
    return obj;
}

void AbstractInlineTextBox::willDestroy(InlineTextBox* inlineTextBox)
{
    if (!gAbstractInlineTextBoxMap)
        return;

    InlineToAbstractInlineTextBoxHashMap::const_iterator it = gAbstractInlineTextBoxMap->find(inlineTextBox);
    if (it != gAbstractInlineTextBoxMap->end()) {
        it->value->detach();
        gAbstractInlineTextBoxMap->remove(inlineTextBox);
    }
}

void AbstractInlineTextBox::detach()
{
    m_renderText = 0;
    m_inlineTextBox = 0;
}

PassRefPtr<AbstractInlineTextBox> AbstractInlineTextBox::nextInlineTextBox() const
{
    if (!m_inlineTextBox)
        return nullptr;

    return getOrCreate(m_renderText, m_inlineTextBox->nextTextBox());
}

LayoutRect AbstractInlineTextBox::bounds() const
{
    if (!m_inlineTextBox || !m_renderText)
        return LayoutRect();

    FloatRect boundaries = m_inlineTextBox->calculateBoundaries();
    return m_renderText->localToAbsoluteQuad(boundaries).enclosingBoundingBox();
}

unsigned AbstractInlineTextBox::len() const
{
    if (!m_inlineTextBox)
        return 0;

    return m_inlineTextBox->len();
}

AbstractInlineTextBox::Direction AbstractInlineTextBox::direction() const
{
    if (!m_inlineTextBox || !m_renderText)
        return LeftToRight;

    if (m_renderText->style()->isHorizontalWritingMode())
        return (m_inlineTextBox->direction() == RTL ? RightToLeft : LeftToRight);
    return (m_inlineTextBox->direction() == RTL ? BottomToTop : TopToBottom);
}

void AbstractInlineTextBox::characterWidths(Vector<float>& widths) const
{
    if (!m_inlineTextBox)
        return;

    m_inlineTextBox->characterWidths(widths);
}

void AbstractInlineTextBox::wordBoundaries(Vector<WordBoundaries>& words) const
{
    if (!m_inlineTextBox)
        return;

    String text = this->text();
    int len = text.length();
    TextBreakIterator* iterator = wordBreakIterator(text, 0, len);

    // FIXME: When http://crbug.com/411764 is fixed, replace this with an ASSERT.
    if (!iterator)
        return;

    int pos = iterator->first();
    while (pos >= 0 && pos < len) {
        int next = iterator->next();
        if (isWordTextBreak(iterator))
            words.append(WordBoundaries(pos, next));
        pos = next;
    }
}

String AbstractInlineTextBox::text() const
{
    if (!m_inlineTextBox || !m_renderText)
        return String();

    unsigned start = m_inlineTextBox->start();
    unsigned len = m_inlineTextBox->len();
    if (Node* node = m_renderText->node()) {
        RefPtrWillBeRawPtr<Range> range = Range::create(node->document());
        range->setStart(node, start, IGNORE_EXCEPTION);
        range->setEnd(node, start + len, IGNORE_EXCEPTION);
        return plainText(range.get(), TextIteratorIgnoresStyleVisibility);
    }

    String result = m_renderText->text().substring(start, len).simplifyWhiteSpace(WTF::DoNotStripWhiteSpace);
    if (m_inlineTextBox->nextTextBox() && m_inlineTextBox->nextTextBox()->start() > m_inlineTextBox->end() && result.length() && !result.right(1).containsOnlyWhitespace())
        return result + " ";
    return result;
}

} // namespace blink
