/*
 * 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(const 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(const StringPiece& bcp47tag) {
  return InitFromBcp47TagImpl(bcp47tag, '-');
}

bool LocaleValue::InitFromBcp47TagImpl(const 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
