/*
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 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 COMPUTER, INC. ``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 COMPUTER, INC. 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.
 */

// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/editing/VisibleUnits.h"

#include "core/editing/EphemeralRange.h"
#include "core/editing/VisiblePosition.h"
#include "platform/text/TextBreakIterator.h"

namespace blink {

namespace {

unsigned EndSentenceBoundary(const UChar* characters,
                             unsigned length,
                             unsigned,
                             BoundarySearchContextAvailability,
                             bool&) {
  TextBreakIterator* iterator = SentenceBreakIterator(characters, length);
  return iterator->next();
}

unsigned NextSentencePositionBoundary(const UChar* characters,
                                      unsigned length,
                                      unsigned,
                                      BoundarySearchContextAvailability,
                                      bool&) {
  // FIXME: This is identical to endSentenceBoundary. This isn't right, it needs
  // to move to the equivlant position in the following sentence.
  TextBreakIterator* iterator = SentenceBreakIterator(characters, length);
  return iterator->following(0);
}

unsigned PreviousSentencePositionBoundary(const UChar* characters,
                                          unsigned length,
                                          unsigned,
                                          BoundarySearchContextAvailability,
                                          bool&) {
  // FIXME: This is identical to startSentenceBoundary. I'm pretty sure that's
  // not right.
  TextBreakIterator* iterator = SentenceBreakIterator(characters, length);
  // FIXME: The following function can return -1; we don't handle that.
  return iterator->preceding(length);
}

unsigned StartSentenceBoundary(const UChar* characters,
                               unsigned length,
                               unsigned,
                               BoundarySearchContextAvailability,
                               bool&) {
  TextBreakIterator* iterator = SentenceBreakIterator(characters, length);
  // FIXME: The following function can return -1; we don't handle that.
  return iterator->preceding(length);
}

// TODO(yosin) This includes the space after the punctuation that marks the end
// of the sentence.
template <typename Strategy>
static VisiblePositionTemplate<Strategy> EndOfSentenceAlgorithm(
    const VisiblePositionTemplate<Strategy>& c) {
  DCHECK(c.IsValid()) << c;
  return CreateVisiblePosition(NextBoundary(c, EndSentenceBoundary),
                               TextAffinity::kUpstreamIfPossible);
}

template <typename Strategy>
VisiblePositionTemplate<Strategy> StartOfSentenceAlgorithm(
    const VisiblePositionTemplate<Strategy>& c) {
  DCHECK(c.IsValid()) << c;
  return CreateVisiblePosition(PreviousBoundary(c, StartSentenceBoundary));
}

}  // namespace

VisiblePosition EndOfSentence(const VisiblePosition& c) {
  return EndOfSentenceAlgorithm<EditingStrategy>(c);
}

VisiblePositionInFlatTree EndOfSentence(const VisiblePositionInFlatTree& c) {
  return EndOfSentenceAlgorithm<EditingInFlatTreeStrategy>(c);
}

EphemeralRange ExpandEndToSentenceBoundary(const EphemeralRange& range) {
  DCHECK(range.IsNotNull());
  const VisiblePosition& visible_end =
      CreateVisiblePosition(range.EndPosition());
  DCHECK(visible_end.IsNotNull());
  const Position& sentence_end = EndOfSentence(visible_end).DeepEquivalent();
  // TODO(editing-dev): |sentenceEnd < range.endPosition()| is possible,
  // which would trigger a DCHECK in EphemeralRange's constructor if we return
  // it directly. However, this shouldn't happen and needs to be fixed.
  return EphemeralRange(
      range.StartPosition(),
      sentence_end.IsNotNull() && sentence_end > range.EndPosition()
          ? sentence_end
          : range.EndPosition());
}

EphemeralRange ExpandRangeToSentenceBoundary(const EphemeralRange& range) {
  DCHECK(range.IsNotNull());
  const VisiblePosition& visible_start =
      CreateVisiblePosition(range.StartPosition());
  DCHECK(visible_start.IsNotNull());
  const Position& sentence_start =
      StartOfSentence(visible_start).DeepEquivalent();
  // TODO(editing-dev): |sentenceStart > range.startPosition()| is possible,
  // which would trigger a DCHECK in EphemeralRange's constructor if we return
  // it directly. However, this shouldn't happen and needs to be fixed.
  return ExpandEndToSentenceBoundary(EphemeralRange(
      sentence_start.IsNotNull() && sentence_start < range.StartPosition()
          ? sentence_start
          : range.StartPosition(),
      range.EndPosition()));
}

VisiblePosition NextSentencePosition(const VisiblePosition& c) {
  DCHECK(c.IsValid()) << c;
  VisiblePosition next =
      CreateVisiblePosition(NextBoundary(c, NextSentencePositionBoundary),
                            TextAffinity::kUpstreamIfPossible);
  return HonorEditingBoundaryAtOrAfter(next, c.DeepEquivalent());
}

VisiblePosition PreviousSentencePosition(const VisiblePosition& c) {
  DCHECK(c.IsValid()) << c;
  VisiblePosition prev = CreateVisiblePosition(
      PreviousBoundary(c, PreviousSentencePositionBoundary));
  return HonorEditingBoundaryAtOrBefore(prev, c.DeepEquivalent());
}

VisiblePosition StartOfSentence(const VisiblePosition& c) {
  return StartOfSentenceAlgorithm<EditingStrategy>(c);
}

VisiblePositionInFlatTree StartOfSentence(const VisiblePositionInFlatTree& c) {
  return StartOfSentenceAlgorithm<EditingInFlatTreeStrategy>(c);
}

}  // namespace blink
