/*
 * Copyright (C) 2012 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 "sky/engine/config.h"
#include "sky/engine/core/editing/SurroundingText.h"

#include "sky/engine/core/dom/Document.h"
#include "sky/engine/core/dom/Element.h"
#include "sky/engine/core/dom/Position.h"
#include "sky/engine/core/dom/Range.h"
#include "sky/engine/core/editing/TextIterator.h"

namespace blink {

SurroundingText::SurroundingText(const Range& range, unsigned maxLength)
    : m_startOffsetInContent(0)
    , m_endOffsetInContent(0)
{
    initialize(range.startPosition(), range.endPosition(), maxLength);
}

SurroundingText::SurroundingText(const Position& position, unsigned maxLength)
    : m_startOffsetInContent(0)
    , m_endOffsetInContent(0)
{
    initialize(position, position, maxLength);
}

void SurroundingText::initialize(const Position& startPosition, const Position& endPosition, unsigned maxLength)
{
    ASSERT(startPosition.document() == endPosition.document());

    const unsigned halfMaxLength = maxLength / 2;

    Document* document = startPosition.document();
    // The position will have no document if it is null (as in no position).
    if (!document)
        return;

    // The forward range starts at the selection end and ends at the document's
    // end. It will then be updated to only contain the text in the text in the
    // right range around the selection.
    RefPtr<Range> forwardRange = Range::create(*document, endPosition, lastPositionInNode(document->documentElement()).parentAnchoredEquivalent());
    CharacterIterator forwardIterator(forwardRange.get());
    // FIXME: why do we stop going trough the text if we were not able to select something on the right?
    if (!forwardIterator.atEnd())
        forwardIterator.advance(maxLength - halfMaxLength);

    forwardRange = forwardIterator.range();
    if (!forwardRange || !Range::create(*document, endPosition, forwardRange->startPosition())->text().length()) {
        ASSERT(forwardRange);
        return;
    }

    // Same as with the forward range but with the backward range. The range
    // starts at the document's start and ends at the selection start and will
    // be updated.
    RefPtr<Range> backwardsRange = Range::create(*document, firstPositionInNode(document->documentElement()).parentAnchoredEquivalent(), startPosition);
    BackwardsCharacterIterator backwardsIterator(backwardsRange.get());
    if (!backwardsIterator.atEnd())
        backwardsIterator.advance(halfMaxLength);

    backwardsRange = backwardsIterator.range();
    if (!backwardsRange) {
        ASSERT(backwardsRange);
        return;
    }

    m_startOffsetInContent = Range::create(*document, backwardsRange->endPosition(), startPosition)->text().length();
    m_endOffsetInContent = Range::create(*document, backwardsRange->endPosition(), endPosition)->text().length();
    m_contentRange = Range::create(*document, backwardsRange->endPosition(), forwardRange->startPosition());
    ASSERT(m_contentRange);
}

PassRefPtr<Range> SurroundingText::rangeFromContentOffsets(unsigned startOffsetInContent, unsigned endOffsetInContent)
{
    if (startOffsetInContent >= endOffsetInContent || endOffsetInContent > content().length())
        return nullptr;

    CharacterIterator iterator(m_contentRange.get());

    ASSERT(!iterator.atEnd());
    iterator.advance(startOffsetInContent);

    ASSERT(iterator.range());
    Position start = iterator.range()->startPosition();

    ASSERT(!iterator.atEnd());
    iterator.advance(endOffsetInContent - startOffsetInContent);

    ASSERT(iterator.range());
    Position end = iterator.range()->startPosition();

    ASSERT(start.document());
    return Range::create(*start.document(), start, end);
}

String SurroundingText::content() const
{
    if (m_contentRange)
        return m_contentRange->text();
    return String();
}

unsigned SurroundingText::startOffsetInContent() const
{
    return m_startOffsetInContent;
}

unsigned SurroundingText::endOffsetInContent() const
{
    return m_endOffsetInContent;
}

} // namespace blink
