// Copyright (c) 2011 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 "base/i18n/break_iterator.h"

#include "base/logging.h"
#include "starboard/types.h"
#include "third_party/icu/source/common/unicode/ubrk.h"
#include "third_party/icu/source/common/unicode/uchar.h"
#include "third_party/icu/source/common/unicode/ustring.h"

namespace base {
namespace i18n {

const size_t npos = static_cast<size_t>(-1);

BreakIterator::BreakIterator(const StringPiece16& str, BreakType break_type)
    : iter_(nullptr),
      string_(str),
      break_type_(break_type),
      prev_(npos),
      pos_(0) {}

BreakIterator::BreakIterator(const StringPiece16& str, const string16& rules)
    : iter_(nullptr),
      string_(str),
      rules_(rules),
      break_type_(RULE_BASED),
      prev_(npos),
      pos_(0) {}

BreakIterator::~BreakIterator() {
  if (iter_)
    ubrk_close(static_cast<UBreakIterator*>(iter_));
}

bool BreakIterator::Init() {
  UErrorCode status = U_ZERO_ERROR;
  UParseError parse_error;
  UBreakIteratorType break_type;
  switch (break_type_) {
    case BREAK_CHARACTER:
      break_type = UBRK_CHARACTER;
      break;
    case BREAK_WORD:
      break_type = UBRK_WORD;
      break;
    case BREAK_LINE:
    case BREAK_NEWLINE:
    case RULE_BASED: // (Keep compiler happy, break_type not used in this case)
      break_type = UBRK_LINE;
      break;
    default:
      NOTREACHED() << "invalid break_type_";
      return false;
  }
  if (break_type_ == RULE_BASED) {
    iter_ = ubrk_openRules(rules_.c_str(),
                           static_cast<int32_t>(rules_.length()),
                           string_.data(),
                           static_cast<int32_t>(string_.size()),
                           &parse_error,
                           &status);
    if (U_FAILURE(status)) {
      NOTREACHED() << "ubrk_openRules failed to parse rule string at line "
          << parse_error.line << ", offset " << parse_error.offset;
    }
  } else {
    iter_ = ubrk_open(break_type, nullptr, string_.data(),
                      static_cast<int32_t>(string_.size()), &status);
    if (U_FAILURE(status)) {
      NOTREACHED() << "ubrk_open failed for type " << break_type
          << " with error " << status;
    }
  }

  if (U_FAILURE(status)) {
    return false;
  }

  // Move the iterator to the beginning of the string.
  ubrk_first(static_cast<UBreakIterator*>(iter_));
  return true;
}

bool BreakIterator::Advance() {
  int32_t pos;
  int32_t status;
  prev_ = pos_;
  switch (break_type_) {
    case BREAK_CHARACTER:
    case BREAK_WORD:
    case BREAK_LINE:
    case RULE_BASED:
      pos = ubrk_next(static_cast<UBreakIterator*>(iter_));
      if (pos == UBRK_DONE) {
        pos_ = npos;
        return false;
      }
      pos_ = static_cast<size_t>(pos);
      return true;
    case BREAK_NEWLINE:
      do {
        pos = ubrk_next(static_cast<UBreakIterator*>(iter_));
        if (pos == UBRK_DONE)
          break;
        pos_ = static_cast<size_t>(pos);
        status = ubrk_getRuleStatus(static_cast<UBreakIterator*>(iter_));
      } while (status >= UBRK_LINE_SOFT && status < UBRK_LINE_SOFT_LIMIT);
      if (pos == UBRK_DONE && prev_ == pos_) {
        pos_ = npos;
        return false;
      }
      return true;
    default:
      NOTREACHED() << "invalid break_type_";
      return false;
  }
}

bool BreakIterator::SetText(const base::char16* text, const size_t length) {
  UErrorCode status = U_ZERO_ERROR;
  ubrk_setText(static_cast<UBreakIterator*>(iter_),
               text, length, &status);
  pos_ = 0;  // implicit when ubrk_setText is done
  prev_ = npos;
  if (U_FAILURE(status)) {
    NOTREACHED() << "ubrk_setText failed";
    return false;
  }
  string_ = StringPiece16(text, length);
  return true;
}

bool BreakIterator::IsWord() const {
  return GetWordBreakStatus() == IS_WORD_BREAK;
}

BreakIterator::WordBreakStatus BreakIterator::GetWordBreakStatus() const {
  int32_t status = ubrk_getRuleStatus(static_cast<UBreakIterator*>(iter_));
  if (break_type_ != BREAK_WORD && break_type_ != RULE_BASED)
    return IS_LINE_OR_CHAR_BREAK;
  // In ICU 60, trying to advance past the end of the text does not change
  // |status| so that |pos_| has to be checked as well as |status|.
  // See http://bugs.icu-project.org/trac/ticket/13447 .
  return (status == UBRK_WORD_NONE || pos_ == npos) ? IS_SKIPPABLE_WORD
                                                    : IS_WORD_BREAK;
}

bool BreakIterator::IsEndOfWord(size_t position) const {
  if (break_type_ != BREAK_WORD && break_type_ != RULE_BASED)
    return false;

  UBreakIterator* iter = static_cast<UBreakIterator*>(iter_);
  UBool boundary = ubrk_isBoundary(iter, static_cast<int32_t>(position));
  int32_t status = ubrk_getRuleStatus(iter);
  return (!!boundary && status != UBRK_WORD_NONE);
}

bool BreakIterator::IsStartOfWord(size_t position) const {
  if (break_type_ != BREAK_WORD && break_type_ != RULE_BASED)
    return false;

  UBreakIterator* iter = static_cast<UBreakIterator*>(iter_);
  UBool boundary = ubrk_isBoundary(iter, static_cast<int32_t>(position));
  ubrk_next(iter);
  int32_t next_status = ubrk_getRuleStatus(iter);
  return (!!boundary && next_status != UBRK_WORD_NONE);
}

bool BreakIterator::IsGraphemeBoundary(size_t position) const {
  if (break_type_ != BREAK_CHARACTER)
    return false;

  UBreakIterator* iter = static_cast<UBreakIterator*>(iter_);
  return !!ubrk_isBoundary(iter, static_cast<int32_t>(position));
}

string16 BreakIterator::GetString() const {
  return GetStringPiece().as_string();
}

StringPiece16 BreakIterator::GetStringPiece() const {
  DCHECK(prev_ != npos && pos_ != npos);
  return string_.substr(prev_, pos_ - prev_);
}

}  // namespace i18n
}  // namespace base
