/*
 * 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 "third_party/blink/renderer/core/editing/visible_units.h"

#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/text_segments.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/text/text_boundaries.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"

namespace blink {

namespace {

// Helpers used during word movement
static bool IsLineBreak(UChar ch) {
  return ch == kNewlineCharacter || ch == kCarriageReturnCharacter;
}

static bool IsWordBreak(UChar ch) {
  return WTF::unicode::IsAlphanumeric(ch) || IsLineBreak(ch) ||
         ch == kLowLineCharacter || WTF::unicode::IsPunct(ch);
}

PositionInFlatTree EndOfWordPositionInternal(const PositionInFlatTree& position,
                                             WordSide side) {
  class Finder final : public TextSegments::Finder {
    STACK_ALLOCATED();

   public:
    Finder(WordSide side) : side_(side) {}

   private:
    Position Find(const String text, unsigned offset) final {
      DCHECK_LE(offset, text.length());
      if (!is_first_time_)
        return FindInternal(text, offset);
      is_first_time_ = false;
      if (side_ == kPreviousWordIfOnBoundary) {
        if (offset == 0)
          return Position::Before(0);
        return FindInternal(text, offset - 1);
      }
      if (offset == text.length())
        return Position::After(offset);
      return FindInternal(text, offset);
    }

    static Position FindInternal(const String text, unsigned offset) {
      DCHECK_LE(offset, text.length());
      TextBreakIterator* it = WordBreakIterator(text.Span16());
      const int result = it->following(offset);
      if (result == kTextBreakDone || result == 0)
        return Position();
      return Position::After(result - 1);
    }

    const WordSide side_;
    bool is_first_time_ = true;
  } finder(side);
  return TextSegments::FindBoundaryForward(position, &finder);
}

PositionInFlatTree NextWordPositionInternal(
    const PositionInFlatTree& position,
    PlatformWordBehavior platform_word_behavior) {
  class Finder final : public TextSegments::Finder {
    STACK_ALLOCATED();

   public:
    Finder(PlatformWordBehavior platform_word_behavior)
        : platform_word_behavior_(platform_word_behavior) {}

   private:
    Position Find(const String text, unsigned offset) final {
      DCHECK_LE(offset, text.length());
      if (!is_first_time_ && static_cast<unsigned>(offset) < text.length()) {
        // These conditions check if we found a valid word break position after
        // another iteration of scanning contents from the position that was
        // passed to this function. Ex: |Hello |World|\n |foo |bar
        // When we are after World|, the first iteration of this loop after call
        // to TextSegments::Finder::find will return empty position as there
        // aren't any meaningful word in that inline_content. In the next
        // iteration of this loop, it fetches the word |foo, so we return the
        // current position as we don't want to skip this valid position by
        // advancing from this position and return |bar instead.
        if (IsWordBreak(text[offset]))
          return SkipWhitespaceIfNeeded(text, offset);
      }
      is_first_time_ = false;
      if (offset == text.length() || text.length() == 0)
        return Position();
      TextBreakIterator* it = WordBreakIterator(text.Span16());
      for (int runner = it->following(offset); runner != kTextBreakDone;
           runner = it->following(runner)) {
        // Move after line break
        if (IsLineBreak(text[runner]))
          return SkipWhitespaceIfNeeded(text, runner);
        // Accumulate punctuation runs
        if (static_cast<unsigned>(runner) < text.length() &&
            WTF::unicode::IsPunct(text[runner])) {
          if (WTF::unicode::IsAlphanumeric(text[runner - 1]))
            return SkipWhitespaceIfNeeded(text, runner);
          continue;
        }
        // We stop searching in the following conditions:
        // 1. When the character preceding the break is
        //    alphanumeric or punctuations or underscore or linebreaks.
        // Only on Windows:
        // 2. When the character preceding the break is a whitespace and
        //    the character following it is an alphanumeric or punctuations
        //    or underscore or linebreaks.
        if (static_cast<unsigned>(runner) < text.length() &&
            IsWordBreak(text[runner - 1]))
          return SkipWhitespaceIfNeeded(text, runner);
        else if (platform_word_behavior_ ==
                     PlatformWordBehavior::kWordSkipSpaces &&
                 static_cast<unsigned>(runner) < text.length() &&
                 IsWhitespace(text[runner - 1]) && IsWordBreak(text[runner]))
          return SkipWhitespaceIfNeeded(text, runner);
      }
      if (text[text.length() - 1] != kNewlineCharacter)
        return Position::After(text.length() - 1);
      return Position();
    }

    Position SkipWhitespaceIfNeeded(const String text, int offset) {
      DCHECK_NE(offset, kTextBreakDone);
      // On Windows next word should skip trailing whitespaces but not line
      // break
      if (platform_word_behavior_ == PlatformWordBehavior::kWordSkipSpaces) {
        for (unsigned runner = static_cast<unsigned>(offset);
             runner < text.length(); ++runner) {
          if (!(IsWhitespace(text[runner]) ||
                WTF::unicode::Direction(text[runner]) ==
                    WTF::unicode::kWhiteSpaceNeutral) ||
              IsLineBreak(text[runner]))
            return Position::Before(runner);
        }
      }
      return Position::Before(offset);
    }

    const PlatformWordBehavior platform_word_behavior_;
    bool is_first_time_ = true;
  } finder(platform_word_behavior);
  return TextSegments::FindBoundaryForward(position, &finder);
}

PositionInFlatTree PreviousWordPositionInternal(
    const PositionInFlatTree& position) {
  class Finder final : public TextSegments::Finder {
    STACK_ALLOCATED();

   private:
    Position Find(const String text, unsigned offset) final {
      DCHECK_LE(offset, text.length());
      if (!is_first_time_ && text.length() > 0 &&
          static_cast<unsigned>(offset) <= text.length()) {
        // These conditions check if we found a valid word break position after
        // another iteration of scanning contents from the position that was
        // passed to this function. Ex: |Hello |World|\n |foo |bar
        // When we are before |foo, the first iteration of this loop after call
        // to TextSegments::Finder::find will return empty position as there
        // aren't any meaningful word in that inline_content. In the next
        // iteration of this loop, it fetches the word World|, so we return the
        // current position as we don't want to skip this valid position by
        // advancing from this position and return |World instead.
        if (IsWordBreak(text[offset - 1]))
          return Position::Before(offset);
      }
      is_first_time_ = false;
      if (!offset || text.length() == 0)
        return Position();
      TextBreakIterator* it = WordBreakIterator(text.Span16());
      int punct_runner = -1;
      for (int runner = it->preceding(offset); runner != kTextBreakDone;
           runner = it->preceding(runner)) {
        // Accumulate punctuation runs
        if (static_cast<unsigned>(runner) < text.length() &&
            WTF::unicode::IsPunct(text[runner])) {
          if (WTF::unicode::IsAlphanumeric(text[runner - 1]))
            return Position::Before(runner);
          punct_runner = runner;
          continue;
        }

        if (punct_runner >= 0)
          return Position::Before(punct_runner);
        // We stop searching when the character following the break is
        // alphanumeric or punctuations or underscore or linebreaks.
        if (static_cast<unsigned>(runner) < text.length() &&
            IsWordBreak(text[runner]))
          return Position::Before(runner);
      }
      return Position::Before(0);
    }
    bool is_first_time_ = true;
  } finder;
  return TextSegments::FindBoundaryBackward(position, &finder);
}

PositionInFlatTree StartOfWordPositionInternal(
    const PositionInFlatTree& position,
    WordSide side) {
  class Finder final : public TextSegments::Finder {
    STACK_ALLOCATED();

   public:
    Finder(WordSide side) : side_(side) {}

   private:
    Position Find(const String text, unsigned offset) final {
      DCHECK_LE(offset, text.length());
      if (!is_first_time_)
        return FindInternal(text, offset);
      is_first_time_ = false;
      if (side_ == kNextWordIfOnBoundary) {
        if (offset == text.length())
          return Position::After(text.length());
        return FindInternal(text, offset + 1);
      }
      if (!offset)
        return Position::Before(offset);
      return FindInternal(text, offset);
    }

    static Position FindInternal(const String text, unsigned offset) {
      DCHECK_LE(offset, text.length());
      TextBreakIterator* it = WordBreakIterator(text.Span16());
      const int result = it->preceding(offset);
      if (result == kTextBreakDone)
        return Position();
      return Position::Before(result);
    }

    const WordSide side_;
    bool is_first_time_ = true;
  } finder(side);
  return TextSegments::FindBoundaryBackward(position, &finder);
}
}  // namespace

PositionInFlatTree EndOfWordPosition(const PositionInFlatTree& start,
                                     WordSide side) {
  return AdjustForwardPositionToAvoidCrossingEditingBoundaries(
             PositionInFlatTreeWithAffinity(
                 EndOfWordPositionInternal(start, side)),
             start)
      .GetPosition();
}

Position EndOfWordPosition(const Position& position, WordSide side) {
  return ToPositionInDOMTree(
      EndOfWordPosition(ToPositionInFlatTree(position), side));
}

// ----
// TODO(editing-dev): Because of word boundary can not be an upstream position,
// we should make this function to return |PositionInFlatTree|.
PositionInFlatTreeWithAffinity NextWordPosition(
    const PositionInFlatTree& start,
    PlatformWordBehavior platform_word_behavior) {
  const PositionInFlatTree next =
      NextWordPositionInternal(start, platform_word_behavior);
  // Note: The word boundary can not be upstream position.
  const PositionInFlatTreeWithAffinity adjusted =
      AdjustForwardPositionToAvoidCrossingEditingBoundaries(
          PositionInFlatTreeWithAffinity(next), start);
  DCHECK_EQ(adjusted.Affinity(), TextAffinity::kDownstream);
  return adjusted;
}

PositionWithAffinity NextWordPosition(
    const Position& start,
    PlatformWordBehavior platform_word_behavior) {
  const PositionInFlatTreeWithAffinity& next =
      NextWordPosition(ToPositionInFlatTree(start), platform_word_behavior);
  return ToPositionInDOMTreeWithAffinity(next);
}

PositionInFlatTreeWithAffinity PreviousWordPosition(
    const PositionInFlatTree& start) {
  const PositionInFlatTree prev = PreviousWordPositionInternal(start);
  return AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
      PositionInFlatTreeWithAffinity(prev), start);
}

PositionWithAffinity PreviousWordPosition(const Position& start) {
  const PositionInFlatTreeWithAffinity& prev =
      PreviousWordPosition(ToPositionInFlatTree(start));
  return ToPositionInDOMTreeWithAffinity(prev);
}

PositionInFlatTree StartOfWordPosition(const PositionInFlatTree& position,
                                       WordSide side) {
  const PositionInFlatTree start = StartOfWordPositionInternal(position, side);
  return AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
             PositionInFlatTreeWithAffinity(start), position)
      .GetPosition();
}

Position StartOfWordPosition(const Position& position, WordSide side) {
  return ToPositionInDOMTree(
      StartOfWordPosition(ToPositionInFlatTree(position), side));
}

}  // namespace blink
