/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "android-base/macros.h"
#include "androidfw/Locale.h"
#include "androidfw/Util.h"

#include <ctype.h>

#include <algorithm>
#include <string>
#include <vector>

using ::android::ResTable_config;
using ::android::StringPiece;

namespace android {

template <size_t N, class Transformer>
static void safe_transform_copy(const char* source, char (&dest)[N], Transformer t) {
  size_t i = 0;
  while (i < N && (*source) != '\0') {
    dest[i++] = t(i, *source);
    source++;
  }
  while (i < N) {
    dest[i++] = '\0';
  }
}

void LocaleValue::set_language(const char* language_chars) {
  safe_transform_copy(language_chars, language, [](size_t, char c) { return ::tolower(c); });
}

void LocaleValue::set_region(const char* region_chars) {
  safe_transform_copy(region_chars, region, [](size_t, char c) { return ::toupper(c); });
}

void LocaleValue::set_script(const char* script_chars) {
  safe_transform_copy(script_chars, script,
                      [](size_t i, char c) { return i ? ::tolower(c) : ::toupper(c); });
}

void LocaleValue::set_variant(const char* variant_chars) {
  safe_transform_copy(variant_chars, variant, [](size_t, char c) { return c; });
}

static inline bool is_alpha(const std::string& str) {
  return std::all_of(std::begin(str), std::end(str), ::isalpha);
}

static inline bool is_number(const std::string& str) {
  return std::all_of(std::begin(str), std::end(str), ::isdigit);
}

bool LocaleValue::InitFromFilterString(StringPiece str) {
  // A locale (as specified in the filter) is an underscore separated name such
  // as "en_US", "en_Latn_US", or "en_US_POSIX".
  std::vector<std::string> parts = util::SplitAndLowercase(str, '_');

  const int num_tags = parts.size();
  bool valid = false;
  if (num_tags >= 1) {
    const std::string& lang = parts[0];
    if (is_alpha(lang) && (lang.length() == 2 || lang.length() == 3)) {
      set_language(lang.c_str());
      valid = true;
    }
  }

  if (!valid || num_tags == 1) {
    return valid;
  }

  // At this point, valid == true && numTags > 1.
  const std::string& part2 = parts[1];
  if ((part2.length() == 2 && is_alpha(part2)) ||
      (part2.length() == 3 && is_number(part2))) {
    set_region(part2.c_str());
  } else if (part2.length() == 4 && is_alpha(part2)) {
    set_script(part2.c_str());
  } else if (part2.length() >= 4 && part2.length() <= 8) {
    set_variant(part2.c_str());
  } else {
    valid = false;
  }

  if (!valid || num_tags == 2) {
    return valid;
  }

  // At this point, valid == true && numTags > 1.
  const std::string& part3 = parts[2];
  if (((part3.length() == 2 && is_alpha(part3)) ||
       (part3.length() == 3 && is_number(part3))) &&
      script[0]) {
    set_region(part3.c_str());
  } else if (part3.length() >= 4 && part3.length() <= 8) {
    set_variant(part3.c_str());
  } else {
    valid = false;
  }

  if (!valid || num_tags == 3) {
    return valid;
  }

  const std::string& part4 = parts[3];
  if (part4.length() >= 4 && part4.length() <= 8) {
    set_variant(part4.c_str());
  } else {
    valid = false;
  }

  if (!valid || num_tags > 4) {
    return false;
  }

  return true;
}

bool LocaleValue::InitFromBcp47Tag(StringPiece bcp47tag) {
  return InitFromBcp47TagImpl(bcp47tag, '-');
}

bool LocaleValue::InitFromBcp47TagImpl(StringPiece bcp47tag, const char separator) {
  std::vector<std::string> subtags = util::SplitAndLowercase(bcp47tag, separator);
  if (subtags.size() == 1) {
    set_language(subtags[0].c_str());
  } else if (subtags.size() == 2) {
    set_language(subtags[0].c_str());

    // The second tag can either be a region, a variant or a script.
    switch (subtags[1].size()) {
      case 2:
      case 3:
        set_region(subtags[1].c_str());
        break;
      case 4:
        if ('0' <= subtags[1][0] && subtags[1][0] <= '9') {
          // This is a variant: fall through
        } else {
          set_script(subtags[1].c_str());
          break;
        }
        FALLTHROUGH_INTENDED;
      case 5:
      case 6:
      case 7:
      case 8:
        set_variant(subtags[1].c_str());
        break;
      default:
        return false;
    }
  } else if (subtags.size() == 3) {
    // The language is always the first subtag.
    set_language(subtags[0].c_str());

    // The second subtag can either be a script or a region code.
    // If its size is 4, it's a script code, else it's a region code.
    if (subtags[1].size() == 4) {
      set_script(subtags[1].c_str());
    } else if (subtags[1].size() == 2 || subtags[1].size() == 3) {
      set_region(subtags[1].c_str());
    } else {
      return false;
    }

    // The third tag can either be a region code (if the second tag was
    // a script), else a variant code.
    if (subtags[2].size() >= 4) {
      set_variant(subtags[2].c_str());
    } else {
      set_region(subtags[2].c_str());
    }
  } else if (subtags.size() == 4) {
    set_language(subtags[0].c_str());
    set_script(subtags[1].c_str());
    set_region(subtags[2].c_str());
    set_variant(subtags[3].c_str());
  } else {
    return false;
  }
  return true;
}

ssize_t LocaleValue::InitFromParts(std::vector<std::string>::iterator iter,
                                   std::vector<std::string>::iterator end) {
  const std::vector<std::string>::iterator start_iter = iter;

  std::string& part = *iter;
  if (part[0] == 'b' && part[1] == '+') {
    // This is a "modified" BCP 47 language tag. Same semantics as BCP 47 tags,
    // except that the separator is "+" and not "-". Skip the prefix 'b+'.
    if (!InitFromBcp47TagImpl(StringPiece(part).substr(2), '+')) {
      return -1;
    }
    ++iter;
  } else {
    if ((part.length() == 2 || part.length() == 3) && is_alpha(part) && part != "car") {
      set_language(part.c_str());
      ++iter;

      if (iter != end) {
        const std::string& region_part = *iter;
        if (region_part.c_str()[0] == 'r' && region_part.length() == 3) {
          set_region(region_part.c_str() + 1);
          ++iter;
        }
      }
    }
  }
  return static_cast<ssize_t>(iter - start_iter);
}

// Make sure the following memcpy's are properly sized.
static_assert(sizeof(ResTable_config::localeScript) == sizeof(LocaleValue::script));
static_assert(sizeof(ResTable_config::localeVariant) == sizeof(LocaleValue::variant));

void LocaleValue::InitFromResTable(const ResTable_config& config) {
  config.unpackLanguage(language);
  config.unpackRegion(region);
  if (config.localeScript[0] && !config.localeScriptWasComputed) {
    memcpy(script, config.localeScript, sizeof(config.localeScript));
  }

  if (config.localeVariant[0]) {
    memcpy(variant, config.localeVariant, sizeof(config.localeVariant));
  }
}

void LocaleValue::WriteTo(ResTable_config* out) const {
  out->packLanguage(language);
  out->packRegion(region);

  if (script[0]) {
    memcpy(out->localeScript, script, sizeof(out->localeScript));
  }

  if (variant[0]) {
    memcpy(out->localeVariant, variant, sizeof(out->localeVariant));
  }
}

}  // namespace android
