/*
 * Copyright (C) 2018 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 "libpixelpowerstats"

#include <android-base/logging.h>
#include <android-base/strings.h>
#include <pixelpowerstats/GenericStateResidencyDataProvider.h>
#include <pixelpowerstats/PowerStatsUtils.h>

#include <cstdio>
#include <cstring>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

namespace android {
namespace hardware {
namespace google {
namespace pixel {
namespace powerstats {

std::vector<StateResidencyConfig> generateGenericStateResidencyConfigs(
        const StateResidencyConfig &stateConfig,
        const std::vector<std::pair<std::string, std::string>> &stateHeaders) {
    std::vector<StateResidencyConfig> stateResidencyConfigs;
    stateResidencyConfigs.reserve(stateHeaders.size());
    for (auto h : stateHeaders) {
        StateResidencyConfig cfg = {stateConfig};
        cfg.name = h.first;
        cfg.header = h.second;
        stateResidencyConfigs.emplace_back(cfg);
    }
    return stateResidencyConfigs;
}

PowerEntityConfig::PowerEntityConfig(const std::vector<StateResidencyConfig> &stateResidencyConfigs)
    : PowerEntityConfig("", stateResidencyConfigs) {}

PowerEntityConfig::PowerEntityConfig(const std::string &header,
                                     const std::vector<StateResidencyConfig> &stateResidencyConfigs)
    : PowerEntityConfig(0, header, stateResidencyConfigs) {}

PowerEntityConfig::PowerEntityConfig(const uint32_t start_id, const std::string &header,
                                     const std::vector<StateResidencyConfig> &stateResidencyConfigs)
    : mHeader(header) {
    mStateResidencyConfigs.reserve(stateResidencyConfigs.size());
    for (uint32_t i = start_id; i < start_id + stateResidencyConfigs.size(); ++i) {
        mStateResidencyConfigs.emplace_back(i, stateResidencyConfigs[i - start_id]);
    }
}

static bool parseState(PowerEntityStateResidencyData *data, const StateResidencyConfig &config,
                       FILE *fp, char **line, size_t *len) {
    size_t numFieldsRead = 0;
    const size_t numFields =
            config.entryCountSupported + config.totalTimeSupported + config.lastEntrySupported;

    while ((numFieldsRead < numFields) && (getline(line, len, fp) != -1)) {
        uint64_t stat = 0;
        // Attempt to extract data from the current line
        if (config.entryCountSupported &&
            utils::extractStat(*line, config.entryCountPrefix, stat)) {
            data->totalStateEntryCount =
                    config.entryCountTransform ? config.entryCountTransform(stat) : stat;
            ++numFieldsRead;
        } else if (config.totalTimeSupported &&
                   utils::extractStat(*line, config.totalTimePrefix, stat)) {
            data->totalTimeInStateMs =
                    config.totalTimeTransform ? config.totalTimeTransform(stat) : stat;
            ++numFieldsRead;
        } else if (config.lastEntrySupported &&
                   utils::extractStat(*line, config.lastEntryPrefix, stat)) {
            data->lastEntryTimestampMs =
                    config.lastEntryTransform ? config.lastEntryTransform(stat) : stat;
            ++numFieldsRead;
        }
    }

    // End of file was reached and not all state data was parsed. Something
    // went wrong
    if (numFieldsRead != numFields) {
        LOG(ERROR) << __func__ << ": failed to parse stats for:" << config.name;
        return false;
    }

    return true;
}

template <class T, class Func>
static auto findNext(const std::vector<T> &collection, FILE *fp, char **line, size_t *len,
                     Func pred) {
    // handling the case when there is no header to look for
    if (pred(collection.front(), "")) {
        return collection.cbegin();
    }

    while (getline(line, len, fp) != -1) {
        for (auto it = collection.cbegin(); it != collection.cend(); ++it) {
            if (pred(*it, *line)) {
                return it;
            }
        }
    }

    return collection.cend();
}

static bool getStateData(
        PowerEntityStateResidencyResult *result,
        const std::vector<std::pair<uint32_t, StateResidencyConfig>> &stateResidencyConfigs,
        FILE *fp, char **line, size_t *len) {
    size_t numStatesRead = 0;
    size_t numStates = stateResidencyConfigs.size();
    auto nextState = stateResidencyConfigs.cbegin();
    auto endState = stateResidencyConfigs.cend();
    auto pred = [](auto a, char const *b) {
        // return true if b matches the header contained in a, ignoring whitespace
        return (a.second.header == android::base::Trim(std::string(b)));
    };

    result->stateResidencyData.resize(numStates);

    // Search for state headers until we have found them all or can't find anymore
    while ((numStatesRead < numStates) &&
           (nextState = findNext<std::pair<uint32_t, StateResidencyConfig>>(
                    stateResidencyConfigs, fp, line, len, pred)) != endState) {
        // Found a matching state header. Parse the contents
        PowerEntityStateResidencyData data = {.powerEntityStateId = nextState->first};
        if (parseState(&data, nextState->second, fp, line, len)) {
            result->stateResidencyData[numStatesRead] = data;
            ++numStatesRead;
        } else {
            break;
        }
    }

    // There was a problem parsing and we failed to get data for all of the states
    if (numStatesRead != numStates) {
        return false;
    }

    return true;
}

bool GenericStateResidencyDataProvider::getResults(
        std::unordered_map<uint32_t, PowerEntityStateResidencyResult> &results) {
    // Using FILE* instead of std::ifstream for performance reasons (b/122253123)
    std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(mPath.c_str(), "r"), fclose);
    if (!fp) {
        PLOG(ERROR) << __func__ << ":Failed to open file " << mPath
                    << " Error = " << strerror(errno);
        return false;
    }

    size_t len = 0;
    char *line = nullptr;
    size_t numEntitiesRead = 0;
    size_t numEntities = mPowerEntityConfigs.size();
    auto nextConfig = mPowerEntityConfigs.cbegin();
    auto endConfig = mPowerEntityConfigs.cend();
    auto pred = [](auto a, char const *b) {
        // return true if b matches the header contained in a, ignoring whitespace
        return (a.second.mHeader == android::base::Trim(std::string(b)));
    };
    bool skipFindNext = false;

    // Search for entity headers until we have found them all or can't find anymore
    while ((numEntitiesRead < numEntities) &&
           (skipFindNext ||
            (nextConfig = findNext<decltype(mPowerEntityConfigs)::value_type>(
                     mPowerEntityConfigs, fp.get(), &line, &len, pred)) != endConfig)) {
        // Found a matching header. Retrieve its state data
        PowerEntityStateResidencyResult result = {.powerEntityId = nextConfig->first};
        if (getStateData(&result, nextConfig->second.mStateResidencyConfigs, fp.get(), &line,
                         &len)) {
            // If a power entity already exists, then merge in the
            // StateResidencyData.
            if (results.find(nextConfig->first) != results.end()) {
                uint32_t size = results[nextConfig->first].stateResidencyData.size();
                results[nextConfig->first].stateResidencyData.resize(
                        size + result.stateResidencyData.size());
                for (uint32_t i = 0; i < result.stateResidencyData.size(); i++) {
                    results[nextConfig->first].stateResidencyData[size + i] =
                            result.stateResidencyData[i];
                }
            } else {
                results.emplace(nextConfig->first, result);
            }
            ++numEntitiesRead;
        } else {
            break;
        }

        // If the header of the next PowerEntityConfig is equal to the
        // current, don't search for it within the file since we'll be search
        // for more states.
        auto currConfig = nextConfig++;
        if (nextConfig != endConfig && nextConfig->second.mHeader == currConfig->second.mHeader) {
            skipFindNext = true;
        } else {
            skipFindNext = false;
        }
    }

    free(line);

    // There was a problem gathering state residency data for one or more entities
    if (numEntitiesRead != numEntities) {
        LOG(ERROR) << __func__ << ":Failed to get results for " << mPath;
        return false;
    }

    return true;
}

void GenericStateResidencyDataProvider::addEntity(uint32_t id, const PowerEntityConfig &config) {
    mPowerEntityConfigs.emplace_back(id, config);
}

std::vector<PowerEntityStateSpace> GenericStateResidencyDataProvider::getStateSpaces() {
    std::vector<PowerEntityStateSpace> stateSpaces;
    stateSpaces.reserve(mPowerEntityConfigs.size());
    for (auto config : mPowerEntityConfigs) {
        PowerEntityStateSpace s = {.powerEntityId = config.first};
        s.states.resize(config.second.mStateResidencyConfigs.size());

        for (uint32_t i = 0; i < config.second.mStateResidencyConfigs.size(); ++i) {
            s.states[i] = {
                    .powerEntityStateId = config.second.mStateResidencyConfigs[i].first,
                    .powerEntityStateName = config.second.mStateResidencyConfigs[i].second.name};
        }
        stateSpaces.emplace_back(s);
    }
    return stateSpaces;
}

}  // namespace powerstats
}  // namespace pixel
}  // namespace google
}  // namespace hardware
}  // namespace android
