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

#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_
#define FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_

#include <stdint.h>

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

#include "TextTable.h"

namespace android {
namespace lshal {

using Pids = std::vector<int32_t>;

enum : unsigned int {
    HWSERVICEMANAGER_LIST, // through defaultServiceManager()->list()
    PTSERVICEMANAGER_REG_CLIENT, // through registerPassthroughClient
    LIST_DLLIB, // through listing dynamic libraries
};
using TableEntrySource = unsigned int;

enum : unsigned int {
    ARCH_UNKNOWN = 0,
    ARCH32       = 1 << 0,
    ARCH64       = 1 << 1,
    ARCH_BOTH    = ARCH32 | ARCH64
};
using Architecture = unsigned int;

enum class TableColumnType : unsigned int {
    INTERFACE_NAME,
    TRANSPORT,
    SERVER_PID,
    SERVER_CMD,
    SERVER_ADDR,
    CLIENT_PIDS,
    CLIENT_CMDS,
    ARCH,
    THREADS,
    RELEASED,
    HASH,
};

enum {
    NO_PID = -1,
    NO_PTR = 0
};

struct TableEntry {
    std::string interfaceName{};
    std::string transport{};
    int32_t serverPid{NO_PID};
    uint32_t threadUsage{0};
    uint32_t threadCount{0};
    std::string serverCmdline{};
    uint64_t serverObjectAddress{NO_PTR};
    Pids clientPids{};
    std::vector<std::string> clientCmdlines{};
    Architecture arch{ARCH_UNKNOWN};
    // empty: unknown, all zeros: unreleased, otherwise: released
    std::string hash{};

    static bool sortByInterfaceName(const TableEntry &a, const TableEntry &b) {
        return a.interfaceName < b.interfaceName;
    };
    static bool sortByServerPid(const TableEntry &a, const TableEntry &b) {
        return a.serverPid < b.serverPid;
    };

    std::string getThreadUsage() const {
        if (threadCount == 0) {
            return "N/A";
        }

        return std::to_string(threadUsage) + "/" + std::to_string(threadCount);
    }

    std::string isReleased() const;

    std::string getField(TableColumnType type) const;

    bool operator==(const TableEntry& other) const;
    std::string to_string() const;
};

using SelectedColumns = std::vector<TableColumnType>;

class Table {
public:
    using Entries = std::vector<TableEntry>;

    Entries::iterator begin() { return mEntries.begin(); }
    Entries::const_iterator begin() const { return mEntries.begin(); }
    Entries::iterator end() { return mEntries.end(); }
    Entries::const_iterator end() const { return mEntries.end(); }
    size_t size() const { return mEntries.size(); }

    void add(TableEntry&& entry) { mEntries.push_back(std::move(entry)); }

    void setSelectedColumns(const SelectedColumns& s) { mSelectedColumns = s; }
    const SelectedColumns& getSelectedColumns() const { return mSelectedColumns; }

    void setDescription(std::string&& d) { mDescription = std::move(d); }

    // Write table content.
    TextTable createTextTable(bool neat = true,
        const std::function<std::string(const std::string&)>& emitDebugInfo = nullptr) const;

private:
    std::string mDescription;
    Entries mEntries;
    SelectedColumns mSelectedColumns;
};

using TableEntryCompare = std::function<bool(const TableEntry &, const TableEntry &)>;

class MergedTable {
public:
    MergedTable(std::vector<const Table*>&& tables) : mTables(std::move(tables)) {}
    TextTable createTextTable();
private:
    std::vector<const Table*> mTables;
};

}  // namespace lshal
}  // namespace android

#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_
