/*
 * 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 specic language governing permissions and
 * limitations under the License.
 */

#include <thread>

#include <getopt.h>
#include <unistd.h>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <sys/types.h>

#include "perfmgr/HintManager.h"

namespace android {
namespace perfmgr {

class NodeVerifier : public HintManager {
  public:
    static bool VerifyNodes(const std::string& config_path) {
        std::string json_doc;

        if (!android::base::ReadFileToString(config_path, &json_doc)) {
            LOG(ERROR) << "Failed to read JSON config from " << config_path;
            return false;
        }

        std::vector<std::unique_ptr<Node>> nodes = ParseNodes(json_doc);
        if (nodes.empty()) {
            LOG(ERROR) << "Failed to parse Nodes section from " << config_path;
            return false;
        }

        for (const auto& node : nodes) {
            std::vector<std::string> values = node->GetValues();
            std::string default_value = values[node->GetDefaultIndex()];
            // Always set to default first
            values.insert(values.begin(), default_value);
            // And reset to default after test
            values.push_back(default_value);
            for (const auto& value : values) {
                if (!android::base::WriteStringToFile(value, node->GetPath())) {
                    LOG(ERROR) << "Failed to write to node: " << node->GetPath()
                               << " with value: " << value;
                    return false;
                }
                LOG(VERBOSE) << "Wrote to node: " << node->GetPath()
                             << " with value: " << value;
            }
        }
        return true;
    }

  private:
    NodeVerifier(sp<NodeLooperThread> nm,
                 const std::map<std::string, std::vector<NodeAction>>& actions)
        : HintManager(nm, actions) {}
};

}  // namespace perfmgr
}  // namespace android

static void printUsage(const char* exec_name) {
    std::string usage = exec_name;
    usage =
        usage +
        " is a command-line tool to verify Nodes in Json config are writable.\n"
        "Usages:\n"
        "    [su system] " +
        exec_name +
        " [options]\n"
        "\n"
        "Options:\n"
        "   --config [PATH], -c\n"
        "       path to Json config file\n\n"
        "   --exec_hint, -e\n"
        "       do hints in Json config\n\n"
        "   --help, -h\n"
        "       print this message\n\n"
        "   --verbose, -v\n"
        "       print verbose log during execution\n\n";

    LOG(INFO) << usage;
}

static void execConfig(const std::string& json_file) {
    std::unique_ptr<android::perfmgr::HintManager> hm =
        android::perfmgr::HintManager::GetFromJSON(json_file);
    if (!hm.get() || !hm->IsRunning()) {
        LOG(ERROR) << "Failed to Parse JSON config";
    }
    std::vector<std::string> hints = hm->GetHints();
    for (const auto& hint : hints) {
        LOG(INFO) << "Do hint: " << hint;
        hm->DoHint(hint);
        std::this_thread::yield();
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
        LOG(INFO) << "End hint: " << hint;
        hm->EndHint(hint);
        std::this_thread::yield();
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }
}

int main(int argc, char* argv[]) {
    android::base::InitLogging(argv, android::base::StderrLogger);

    if (getuid() == 0) {
        LOG(WARNING) << "Running as root might mask node permission";
    }

    std::string config_path;
    bool exec_hint = false;
    while (true) {
        static struct option opts[] = {
            {"config", required_argument, nullptr, 'c'},
            {"exec_hint", no_argument, nullptr, 'e'},
            {"help", no_argument, nullptr, 'h'},
            {"verbose", no_argument, nullptr, 'v'},
            {0, 0, 0, 0}  // termination of the option list
        };

        int option_index = 0;
        int c = getopt_long(argc, argv, "c:ehv", opts, &option_index);
        if (c == -1) {
            break;
        }

        switch (c) {
            case 'c':
                config_path = optarg;
                break;
            case 'e':
                exec_hint = true;
                break;
            case 'v':
                android::base::SetMinimumLogSeverity(android::base::VERBOSE);
                break;
            case 'h':
                printUsage(argv[0]);
                return 0;
            default:
                // getopt already prints "invalid option -- %c" for us.
                return 1;
        }
    }

    if (config_path.empty()) {
        LOG(ERROR) << "Need specify JSON config";
        printUsage(argv[0]);
        return 1;
    }

    if (exec_hint) {
        execConfig(config_path);
        return 0;
    }

    if (android::perfmgr::NodeVerifier::VerifyNodes(config_path)) {
        LOG(INFO) << "Verified writing to JSON config";
        return 0;
    } else {
        LOG(ERROR) << "Failed to verify nodes in JSON config";
        return 1;
    }
}
