/*
 * 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 "Locale.h"
#include "Util.h"

#include <algorithm>
#include <ctype.h>
#include <string>
#include <vector>

namespace aapt {

using android::ResTable_config;

void LocaleValue::setLanguage(const char* languageChars) {
     size_t i = 0;
     while ((*languageChars) != '\0') {
          language[i++] = ::tolower(*languageChars);
          languageChars++;
     }
}

void LocaleValue::setRegion(const char* regionChars) {
    size_t i = 0;
    while ((*regionChars) != '\0') {
         region[i++] = ::toupper(*regionChars);
         regionChars++;
    }
}

void LocaleValue::setScript(const char* scriptChars) {
    size_t i = 0;
    while ((*scriptChars) != '\0') {
         if (i == 0) {
             script[i++] = ::toupper(*scriptChars);
         } else {
             script[i++] = ::tolower(*scriptChars);
         }
         scriptChars++;
    }
}

void LocaleValue::setVariant(const char* variantChars) {
     size_t i = 0;
     while ((*variantChars) != '\0') {
          variant[i++] = *variantChars;
          variantChars++;
     }
}

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

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

bool LocaleValue::initFromFilterString(const std::string& 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 numTags = parts.size();
     bool valid = false;
     if (numTags >= 1) {
         const std::string& lang = parts[0];
         if (isAlpha(lang) && (lang.length() == 2 || lang.length() == 3)) {
             setLanguage(lang.c_str());
             valid = true;
         }
     }

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

     // At this point, valid == true && numTags > 1.
     const std::string& part2 = parts[1];
     if ((part2.length() == 2 && isAlpha(part2)) ||
         (part2.length() == 3 && isNumber(part2))) {
         setRegion(part2.c_str());
     } else if (part2.length() == 4 && isAlpha(part2)) {
         setScript(part2.c_str());
     } else if (part2.length() >= 5 && part2.length() <= 8) {
         setVariant(part2.c_str());
     } else {
         valid = false;
     }

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

     // At this point, valid == true && numTags > 1.
     const std::string& part3 = parts[2];
     if (((part3.length() == 2 && isAlpha(part3)) ||
         (part3.length() == 3 && isNumber(part3))) && script[0]) {
         setRegion(part3.c_str());
     } else if (part3.length() >= 5 && part3.length() <= 8) {
         setVariant(part3.c_str());
     } else {
         valid = false;
     }

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

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

     if (!valid || numTags > 4) {
         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 startIter = 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 "-".
        std::vector<std::string> subtags = util::splitAndLowercase(part, '+');
        subtags.erase(subtags.begin());
        if (subtags.size() == 1) {
            setLanguage(subtags[0].c_str());
        } else if (subtags.size() == 2) {
            setLanguage(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:
                    setRegion(subtags[1].c_str());
                    break;
                case 4:
                    setScript(subtags[1].c_str());
                    break;
                case 5:
                case 6:
                case 7:
                case 8:
                    setVariant(subtags[1].c_str());
                    break;
                default:
                    return -1;
            }
        } else if (subtags.size() == 3) {
            // The language is always the first subtag.
            setLanguage(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) {
                setScript(subtags[1].c_str());
            } else if (subtags[1].size() == 2 || subtags[1].size() == 3) {
                setRegion(subtags[1].c_str());
            } else {
                return -1;
            }

            // 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) {
                setVariant(subtags[2].c_str());
            } else {
                setRegion(subtags[2].c_str());
            }
        } else if (subtags.size() == 4) {
            setLanguage(subtags[0].c_str());
            setScript(subtags[1].c_str());
            setRegion(subtags[2].c_str());
            setVariant(subtags[3].c_str());
        } else {
            return -1;
        }

        ++iter;

    } else {
        if ((part.length() == 2 || part.length() == 3)
                && isAlpha(part) && part != "car") {
            setLanguage(part.c_str());
            ++iter;

            if (iter != end) {
                const std::string& regionPart = *iter;
                if (regionPart.c_str()[0] == 'r' && regionPart.length() == 3) {
                    setRegion(regionPart.c_str() + 1);
                    ++iter;
                }
            }
        }
    }

    return static_cast<ssize_t>(iter - startIter);
}


std::string LocaleValue::toDirName() const {
    std::string dirName;
    if (language[0]) {
        dirName += language;
    } else {
        return dirName;
    }

    if (script[0]) {
        dirName += "-s";
        dirName += script;
    }

    if (region[0]) {
        dirName += "-r";
        dirName += region;
    }

    if (variant[0]) {
        dirName += "-v";
        dirName += variant;
    }

    return dirName;
}

void LocaleValue::initFromResTable(const ResTable_config& config) {
    config.unpackLanguage(language);
    config.unpackRegion(region);
    if (config.localeScript[0]) {
        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 aapt
