// 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/string_search.h"
#include "base/logging.h"

#include "unicode/usearch.h"

namespace {

#if !defined(UCONFIG_NO_COLLATION)
bool CollationSensitiveStringSearch(const string16& find_this,
                                    const string16& in_this,
                                    UCollationStrength strength,
                                    size_t* match_index,
                                    size_t* match_length) {
  UErrorCode status = U_ZERO_ERROR;

  UStringSearch* search = usearch_open(find_this.data(), -1,
                                       in_this.data(), -1,
                                       uloc_getDefault(),
                                       NULL,  // breakiter
                                       &status);

  // Default to basic substring search if usearch fails. According to
  // http://icu-project.org/apiref/icu4c/usearch_8h.html, usearch_open will fail
  // if either |find_this| or |in_this| are empty. In either case basic
  // substring search will give the correct return value.
  if (!U_SUCCESS(status)) {
    size_t index = in_this.find(find_this);
    if (index == string16::npos) {
      return false;
    } else {
      if (match_index)
        *match_index = index;
      if (match_length)
        *match_length = find_this.size();
      return true;
    }
  }

  UCollator* collator = usearch_getCollator(search);
  ucol_setStrength(collator, strength);
  usearch_reset(search);

  int32_t index = usearch_first(search, &status);
  if (!U_SUCCESS(status) || index == USEARCH_DONE) {
    usearch_close(search);
    return false;
  }

  if (match_index)
    *match_index = static_cast<size_t>(index);
  if (match_length)
    *match_length = static_cast<size_t>(usearch_getMatchedLength(search));

  usearch_close(search);
  return true;
}
#endif  //  !defined(UCONFIG_NO_COLLATION)

}  // namespace

namespace base {
namespace i18n {

bool StringSearchIgnoringCaseAndAccents(const string16& find_this,
                                        const string16& in_this,
                                        size_t* match_index,
                                        size_t* match_length) {
#if defined(UCONFIG_NO_COLLATION)
  // If collation is not used, and this function is called, try to do the most
  // correct thing possible (basic substring search).
  std::string::size_type index = in_this.find(find_this);
  if (index == string16::npos) {
    return false;
  } else {
    if (match_index)
      *match_index = index;
    if (match_length)
      *match_length = find_this.size();
    return true;
  }
#else
  return CollationSensitiveStringSearch(find_this,
                                        in_this,
                                        UCOL_PRIMARY,
                                        match_index,
                                        match_length);
#endif  // defined(UCONFIG_NO_COLLATION)
}

}  // namespace i18n
}  // namespace base
