// Copyright 2013 The Flutter 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 "string_utils.h"

#include <array>
#include <cctype>
#include <codecvt>
#include <locale>
#include <regex>
#include <sstream>

#include "flutter/fml/string_conversion.h"
#include "third_party/dart/runtime/third_party/double-conversion/src/double-conversion.h"

#include "no_destructor.h"

namespace base {

using double_conversion::DoubleToStringConverter;
using double_conversion::StringBuilder;

namespace {
constexpr char kExponentChar = 'e';
constexpr char kInfinitySymbol[] = "Infinity";
constexpr char kNaNSymbol[] = "NaN";

// The number of digits after the decimal we allow before switching to
// exponential representation.
constexpr int kDecimalInShortestLow = -6;
// The number of digits before the decimal we allow before switching to
// exponential representation.
constexpr int kDecimalInShortestHigh = 12;
constexpr int kConversionFlags =
    DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN;

const DoubleToStringConverter& GetDoubleToStringConverter() {
  static DoubleToStringConverter converter(
      kConversionFlags, kInfinitySymbol, kNaNSymbol, kExponentChar,
      kDecimalInShortestLow, kDecimalInShortestHigh, 0, 0);
  return converter;
}

std::string NumberToStringImpl(double number, bool is_single_precision) {
  if (number == 0.0) {
    return "0";
  }

  constexpr int kBufferSize = 128;
  std::array<char, kBufferSize> char_buffer;
  StringBuilder builder(char_buffer.data(), char_buffer.size());
  if (is_single_precision) {
    GetDoubleToStringConverter().ToShortestSingle(static_cast<float>(number),
                                                  &builder);
  } else {
    GetDoubleToStringConverter().ToShortest(number, &builder);
  }
  return std::string(char_buffer.data(), builder.position());
}
}  // namespace

std::u16string ASCIIToUTF16(std::string src) {
  return std::u16string(src.begin(), src.end());
}

std::u16string UTF8ToUTF16(std::string src) {
  return fml::Utf8ToUtf16(src);
}

std::string UTF16ToUTF8(std::u16string src) {
  return fml::Utf16ToUtf8(src);
}

std::u16string WideToUTF16(const std::wstring& src) {
  return std::u16string(src.begin(), src.end());
}

std::wstring UTF16ToWide(const std::u16string& src) {
  return std::wstring(src.begin(), src.end());
}

std::u16string NumberToString16(float number) {
  return ASCIIToUTF16(NumberToString(number));
}

std::u16string NumberToString16(int32_t number) {
  return ASCIIToUTF16(NumberToString(number));
}

std::u16string NumberToString16(unsigned int number) {
  return ASCIIToUTF16(NumberToString(number));
}

std::u16string NumberToString16(double number) {
  return ASCIIToUTF16(NumberToString(number));
}

std::string NumberToString(int32_t number) {
  return std::to_string(number);
}

std::string NumberToString(unsigned int number) {
  return std::to_string(number);
}

std::string NumberToString(float number) {
  return NumberToStringImpl(number, true);
}

std::string NumberToString(double number) {
  return NumberToStringImpl(number, false);
}

std::string JoinString(std::vector<std::string> tokens, std::string delimiter) {
  std::ostringstream imploded;
  for (size_t i = 0; i < tokens.size(); i++) {
    if (i == tokens.size() - 1) {
      imploded << tokens[i];
    } else {
      imploded << tokens[i] << delimiter;
    }
  }
  return imploded.str();
}

std::u16string JoinString(std::vector<std::u16string> tokens,
                          std::u16string delimiter) {
  std::u16string result;
  for (size_t i = 0; i < tokens.size(); i++) {
    if (i == tokens.size() - 1) {
      result.append(tokens[i]);
    } else {
      result.append(tokens[i]);
      result.append(delimiter);
    }
  }
  return result;
}

void ReplaceChars(std::string in,
                  std::string from,
                  std::string to,
                  std::string* out) {
  size_t pos = in.find(from);
  while (pos != std::string::npos) {
    in.replace(pos, from.size(), to);
    pos = in.find(from, pos + to.size());
  }
  *out = in;
}

void ReplaceChars(std::u16string in,
                  std::u16string from,
                  std::u16string to,
                  std::u16string* out) {
  size_t pos = in.find(from);
  while (pos != std::u16string::npos) {
    in.replace(pos, from.size(), to);
    pos = in.find(from, pos + to.size());
  }
  *out = in;
}

const std::string& EmptyString() {
  static const base::NoDestructor<std::string> s;
  return *s;
}

std::string ToUpperASCII(std::string str) {
  std::string ret;
  ret.reserve(str.size());
  for (size_t i = 0; i < str.size(); i++)
    ret.push_back(std::toupper(str[i]));
  return ret;
}

std::string ToLowerASCII(std::string str) {
  std::string ret;
  ret.reserve(str.size());
  for (size_t i = 0; i < str.size(); i++)
    ret.push_back(std::tolower(str[i]));
  return ret;
}

bool LowerCaseEqualsASCII(std::string a, std::string b) {
  std::string lower_a = ToLowerASCII(a);
  return lower_a.compare(ToLowerASCII(b)) == 0;
}

bool ContainsOnlyChars(std::u16string str, char16_t ch) {
  return std::find_if(str.begin(), str.end(),
                      [ch](char16_t c) { return c != ch; }) == str.end();
}

}  // namespace base
