/*
 * 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.
 */

#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
#include <unistd.h>

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <android-base/stringprintf.h>
#include <meminfo/procmeminfo.h>

using Vma = ::android::meminfo::Vma;
using ProcMemInfo = ::android::meminfo::ProcMemInfo;
using MemUsage = ::android::meminfo::MemUsage;

// Global flags to control procmem output

// Set to use page idle bits for working set detection
bool use_pageidle = false;
// hides map entries with zero rss
bool hide_zeroes = false;
// Reset working set and exit
bool reset_wss = false;
// Show working set, mutually exclusive with reset_wss;
bool show_wss = false;

[[noreturn]] static void usage(int exit_status) {
    fprintf(stderr,
            "Usage: %s [-i] [ -w | -W ] [ -p | -m ] [ -h ] pid\n"
            "    -i  Uses idle page tracking for working set statistics.\n"
            "    -w  Displays statistics for the working set only.\n"
            "    -W  Resets the working set of the process.\n"
            "    -p  Sort by PSS.\n"
            "    -u  Sort by USS.\n"
            "    -m  Sort by mapping order (as read from /proc).\n"
            "    -h  Hide maps with no RSS.\n",
            getprogname());

    exit(exit_status);
}

static void print_separator(std::stringstream& ss) {
    if (show_wss) {
        ss << ::android::base::StringPrintf("%7s  %7s  %7s  %7s  %7s  %7s  %7s  %s\n", "-------",
                                            "-------", "-------", "-------", "-------", "-------",
                                            "-------", "");
        return;
    }
    ss << ::android::base::StringPrintf("%7s  %7s  %7s  %7s  %7s  %7s  %7s  %7s  %s\n", "-------",
                                        "-------", "-------", "-------", "-------", "-------",
                                        "-------", "-------", "");
}

static void print_header(std::stringstream& ss) {
    if (show_wss) {
        ss << ::android::base::StringPrintf("%7s  %7s  %7s  %7s  %7s  %7s  %7s  %s\n", "WRss",
                                            "WPss", "WUss", "WShCl", "WShDi", "WPrCl", "WPrDi",
                                            "Name");
    } else {
        ss << ::android::base::StringPrintf("%7s  %7s  %7s  %7s  %7s  %7s  %7s  %7s  %s\n", "Vss",
                                            "Rss", "Pss", "Uss", "ShCl", "ShDi", "PrCl", "PrDi",
                                            "Name");
    }
    print_separator(ss);
}

static void print_stats(std::stringstream& ss, const MemUsage& stats) {
    if (!show_wss) {
        ss << ::android::base::StringPrintf("%6" PRIu64 "K  ", stats.vss / 1024);
    }

    ss << ::android::base::StringPrintf("%6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64
                                        "K  %6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  ",
                                        stats.rss / 1024, stats.pss / 1024, stats.uss / 1024,
                                        stats.shared_clean / 1024, stats.shared_dirty / 1024,
                                        stats.private_clean / 1024, stats.private_dirty / 1024);
}

static int show(const MemUsage& proc_stats, const std::vector<Vma>& maps) {
    std::stringstream ss;
    print_header(ss);
    for (auto& vma : maps) {
        const MemUsage& vma_stats = vma.usage;
        if (hide_zeroes && vma_stats.rss == 0) {
            continue;
        }
        print_stats(ss, vma_stats);
        ss << vma.name << std::endl;
    }
    print_separator(ss);
    print_stats(ss, proc_stats);
    ss << "TOTAL" << std::endl;
    std::cout << ss.str();

    return 0;
}

int main(int argc, char* argv[]) {
    int opt;
    auto pss_sort = [](const Vma& a, const Vma& b) {
        uint64_t pss_a = a.usage.pss;
        uint64_t pss_b = b.usage.pss;
        return pss_a > pss_b;
    };

    auto uss_sort = [](const Vma& a, const Vma& b) {
        uint64_t uss_a = a.usage.uss;
        uint64_t uss_b = b.usage.uss;
        return uss_a > uss_b;
    };

    std::function<bool(const Vma& a, const Vma& b)> sort_func = nullptr;
    while ((opt = getopt(argc, argv, "himpuWw")) != -1) {
        switch (opt) {
            case 'h':
                hide_zeroes = true;
                break;
            case 'i':
                // TODO: libmeminfo doesn't support the flag to chose
                // between idle page tracking vs clear_refs. So for now,
                // this flag is unused and the library defaults to using
                // /proc/<pid>/clear_refs for finding the working set.
                use_pageidle = true;
                break;
            case 'm':
                // this is the default
                break;
            case 'p':
                sort_func = pss_sort;
                break;
            case 'u':
                sort_func = uss_sort;
                break;
            case 'W':
                reset_wss = true;
                break;
            case 'w':
                show_wss = true;
                break;
            case '?':
                usage(EXIT_SUCCESS);
            default:
                usage(EXIT_FAILURE);
        }
    }

    if (optind != (argc - 1)) {
        fprintf(stderr, "Need exactly one pid at the end\n");
        usage(EXIT_FAILURE);
    }

    pid_t pid = atoi(argv[optind]);
    if (pid == 0) {
        std::cerr << "Invalid process id" << std::endl;
        exit(EXIT_FAILURE);
    }

    if (reset_wss) {
        if (!ProcMemInfo::ResetWorkingSet(pid)) {
            std::cerr << "Failed to reset working set of pid : " << pid << std::endl;
            exit(EXIT_FAILURE);
        }
        return 0;
    }

    ProcMemInfo proc(pid, show_wss);
    const MemUsage& proc_stats = proc.Usage();
    std::vector<Vma> maps(proc.Maps());
    if (sort_func != nullptr) {
        std::sort(maps.begin(), maps.end(), sort_func);
    }

    return show(proc_stats, maps);
}
