/*
 * Copyright (C) 2008 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.
 */

#define LOG_TAG "PropertyMap"

#include <input/PropertyMap.h>
#include <log/log.h>

// Enables debug output for the parser.
#define DEBUG_PARSER 0

// Enables debug output for parser performance.
#define DEBUG_PARSER_PERFORMANCE 0

namespace android {

static const char* WHITESPACE = " \t\r";
static const char* WHITESPACE_OR_PROPERTY_DELIMITER = " \t\r=";

// --- PropertyMap ---

PropertyMap::PropertyMap() {}

PropertyMap::~PropertyMap() {}

void PropertyMap::clear() {
    mProperties.clear();
}

void PropertyMap::addProperty(const std::string& key, const std::string& value) {
    mProperties.emplace(key, value);
}

bool PropertyMap::hasProperty(const std::string& key) const {
    return mProperties.find(key) != mProperties.end();
}

bool PropertyMap::tryGetProperty(const std::string& key, std::string& outValue) const {
    auto it = mProperties.find(key);
    if (it == mProperties.end()) {
        return false;
    }

    outValue = it->second;
    return true;
}

bool PropertyMap::tryGetProperty(const std::string& key, bool& outValue) const {
    int32_t intValue;
    if (!tryGetProperty(key, intValue)) {
        return false;
    }

    outValue = intValue;
    return true;
}

bool PropertyMap::tryGetProperty(const std::string& key, int32_t& outValue) const {
    std::string stringValue;
    if (!tryGetProperty(key, stringValue) || stringValue.length() == 0) {
        return false;
    }

    char* end;
    int32_t value = static_cast<int32_t>(strtol(stringValue.c_str(), &end, 10));
    if (*end != '\0') {
        ALOGW("Property key '%s' has invalid value '%s'.  Expected an integer.", key.c_str(),
              stringValue.c_str());
        return false;
    }
    outValue = value;
    return true;
}

bool PropertyMap::tryGetProperty(const std::string& key, float& outValue) const {
    std::string stringValue;
    if (!tryGetProperty(key, stringValue) || stringValue.length() == 0) {
        return false;
    }

    char* end;
    float value = strtof(stringValue.c_str(), &end);
    if (*end != '\0') {
        ALOGW("Property key '%s' has invalid value '%s'.  Expected a float.", key.c_str(),
              stringValue.c_str());
        return false;
    }
    outValue = value;
    return true;
}

void PropertyMap::addAll(const PropertyMap* map) {
    for (const auto& [key, value] : map->mProperties) {
        mProperties.emplace(key, value);
    }
}

android::base::Result<std::unique_ptr<PropertyMap>> PropertyMap::load(const char* filename) {
    std::unique_ptr<PropertyMap> outMap = std::make_unique<PropertyMap>();
    if (outMap == nullptr) {
        return android::base::Error(NO_MEMORY) << "Error allocating property map.";
    }

    Tokenizer* rawTokenizer;
    status_t status = Tokenizer::open(String8(filename), &rawTokenizer);
    std::unique_ptr<Tokenizer> tokenizer(rawTokenizer);
    if (status) {
        ALOGE("Error %d opening property file %s.", status, filename);
    } else {
#if DEBUG_PARSER_PERFORMANCE
            nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
#endif
            Parser parser(outMap.get(), tokenizer.get());
            status = parser.parse();
#if DEBUG_PARSER_PERFORMANCE
            nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
            ALOGD("Parsed property file '%s' %d lines in %0.3fms.",
                  tokenizer->getFilename().string(), tokenizer->getLineNumber(),
                  elapsedTime / 1000000.0);
#endif
            if (status) {
                return android::base::Error(BAD_VALUE) << "Could not parse " << filename;
            }
    }
    return std::move(outMap);
}

// --- PropertyMap::Parser ---

PropertyMap::Parser::Parser(PropertyMap* map, Tokenizer* tokenizer)
      : mMap(map), mTokenizer(tokenizer) {}

PropertyMap::Parser::~Parser() {}

status_t PropertyMap::Parser::parse() {
    while (!mTokenizer->isEof()) {
#if DEBUG_PARSER
        ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
              mTokenizer->peekRemainderOfLine().string());
#endif

        mTokenizer->skipDelimiters(WHITESPACE);

        if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
            String8 keyToken = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER);
            if (keyToken.isEmpty()) {
                ALOGE("%s: Expected non-empty property key.", mTokenizer->getLocation().string());
                return BAD_VALUE;
            }

            mTokenizer->skipDelimiters(WHITESPACE);

            if (mTokenizer->nextChar() != '=') {
                ALOGE("%s: Expected '=' between property key and value.",
                      mTokenizer->getLocation().string());
                return BAD_VALUE;
            }

            mTokenizer->skipDelimiters(WHITESPACE);

            String8 valueToken = mTokenizer->nextToken(WHITESPACE);
            if (valueToken.find("\\", 0) >= 0 || valueToken.find("\"", 0) >= 0) {
                ALOGE("%s: Found reserved character '\\' or '\"' in property value.",
                      mTokenizer->getLocation().string());
                return BAD_VALUE;
            }

            mTokenizer->skipDelimiters(WHITESPACE);
            if (!mTokenizer->isEol()) {
                ALOGE("%s: Expected end of line, got '%s'.", mTokenizer->getLocation().string(),
                      mTokenizer->peekRemainderOfLine().string());
                return BAD_VALUE;
            }

            if (mMap->hasProperty(keyToken.string())) {
                ALOGE("%s: Duplicate property value for key '%s'.",
                      mTokenizer->getLocation().string(), keyToken.string());
                return BAD_VALUE;
            }

            mMap->addProperty(keyToken.string(), valueToken.string());
        }

        mTokenizer->nextLine();
    }
    return OK;
}

} // namespace android
