#ifndef KMMETADATA_H
#define KMMETADATA_H

#include "KMCommonTypePrivate.h"
#include "KMKeyFile.h"

#define METADATA_GROUP_APPLICATION "Application"
#define METADATA_GROUP_RUNTIME "Runtime"
#define METADATA_KEY_COMMAND "command"
#define METADATA_KEY_NAME "name"
#define METADATA_KEY_REQUIRED_KAIMING "required-kaiming"
#define METADATA_KEY_RUNTIME "runtime"
#define METADATA_KEY_SDK "sdk"
#define METADATA_KEY_BASE "base"
#define METADATA_KEY_TAGS "tags"

#define METADATA_GROUP_CONTEXT "Context"
#define METADATA_KEY_SHARED "shared"
#define METADATA_KEY_SOCKETS "sockets"
#define METADATA_KEY_FILESYSTEMS "filesystems"
#define METADATA_KEY_PERSISTENT "persistent"
#define METADATA_KEY_DEVICES "devices"
#define METADATA_KEY_FEATURES "features"
#define METADATA_KEY_UNSET_ENVIRONMENT "unset-environment"

#define METADATA_GROUP_INSTANCE "Instance"
#define METADATA_KEY_INSTANCE_PATH "instance-path"
#define METADATA_KEY_INSTANCE_ID "instance-id"
#define METADATA_KEY_ORIGINAL_APP_PATH "original-app-path"
#define METADATA_KEY_APP_PATH "app-path"
#define METADATA_KEY_APP_COMMIT "app-commit"
#define METADATA_KEY_APP_EXTENSIONS "app-extensions"
#define METADATA_KEY_ARCH "arch"
#define METADATA_KEY_BRANCH "branch"
#define METADATA_KEY_KAIMING_VERSION "kaiming-version"
#define METADATA_KEY_ORIGINAL_RUNTIME_PATH "original-runtime-path"
#define METADATA_KEY_RUNTIME_PATH "runtime-path"
#define METADATA_KEY_RUNTIME_COMMIT "runtime-commit"
#define METADATA_KEY_RUNTIME_EXTENSIONS "runtime-extensions"
#define METADATA_KEY_SESSION_BUS_PROXY "session-bus-proxy"
#define METADATA_KEY_SYSTEM_BUS_PROXY "system-bus-proxy"
#define METADATA_KEY_EXTRA_ARGS "extra-args"
#define METADATA_KEY_SANDBOX "sandbox"
#define METADATA_KEY_BUILD "build"
#define METADATA_KEY_DEVEL "devel"

#define METADATA_GROUP_SESSION_BUS_POLICY "Session Bus Policy"
#define METADATA_GROUP_SYSTEM_BUS_POLICY "System Bus Policy"
#define METADATA_GROUP_PREFIX_POLICY "Policy "
#define METADATA_GROUP_ENVIRONMENT "Environment"

#define METADATA_GROUP_PREFIX_EXTENSION "Extension "
#define METADATA_KEY_ADD_LD_PATH "add-ld-path"
#define METADATA_KEY_AUTODELETE "autodelete"
#define METADATA_KEY_DIRECTORY "directory"
#define METADATA_KEY_DOWNLOAD_IF "download-if"
#define METADATA_KEY_ENABLE_IF "enable-if"
#define METADATA_KEY_AUTOPRUNE_UNLESS "autoprune-unless"
#define METADATA_KEY_MERGE_DIRS "merge-dirs"
#define METADATA_KEY_NO_AUTODOWNLOAD "no-autodownload"
#define METADATA_KEY_SUBDIRECTORIES "subdirectories"
#define METADATA_KEY_SUBDIRECTORY_SUFFIX "subdirectory-suffix"
#define METADATA_KEY_LOCALE_SUBSET "locale-subset"
#define METADATA_KEY_VERSION "version"
#define METADATA_KEY_VERSIONS "versions"

#define METADATA_KEY_COLLECTION_ID "collection-id"

#define METADATA_GROUP_EXTRA_DATA "Extra Data"
#define METADATA_KEY_EXTRA_DATA_CHECKSUM "checksum"
#define METADATA_KEY_EXTRA_DATA_INSTALLED_SIZE "installed-size"
#define METADATA_KEY_EXTRA_DATA_NAME "name"
#define METADATA_KEY_EXTRA_DATA_SIZE "size"
#define METADATA_KEY_EXTRA_DATA_URI "uri"
#define METADATA_KEY_NO_RUNTIME "NoRuntime"

#define METADATA_GROUP_EXTENSION_OF "ExtensionOf"
#define METADATA_KEY_PRIORITY "priority"
#define METADATA_KEY_REF "ref"
#define METADATA_KEY_TAG "tag"

#define METADATA_GROUP_DCONF "X-DConf"
#define METADATA_KEY_DCONF_PATHS "paths"
#define METADATA_KEY_DCONF_MIGRATE_PATH "migrate-path"

struct KMExtension
{
public:
    std::string name;

    bool autodelete = false;
    std::string addLdPath;
    std::string directory;
    std::string downloadIf;
    std::string enableIf;
    std::string autopruneUnless;
    std::list<std::string> mergeDirs;
    bool noAutodownload = false;
    bool subdirectories = false;
    bool localeSubset = false;
    std::string subdirectorySuffix;
    std::string version;
    std::list<std::string> versions;

    bool needsTmpfs = false;
    bool isUnmaintained = false;
    KMRef ref;
    std::string extensionFilesPath;
    int priority;

    // 重载小于运算符，用于容器中排序
    bool operator<(const KMExtension &other) const { return directory.compare(other.directory) < 0 ? true : false; }

    // 重载大于运算符，用于容器中排序
    // bool operator>(const KMExtension& other) const {
    //     return directory.compare(other.directory) > 0 ? true : false;
    // }
};

/**
 * @brief Parse metadate file
 */
class KMMetaData : public KMKeyFile
{
public:
    KMMetaData(bool isApp = true);
    ~KMMetaData();

    bool load(const std::string &metafile);

    const std::string &getCommand() { return d->m_applicationCommand; }

    const std::string &getRuntime() { return d->m_applicationRuntime; }

    const std::string &getSdk() { return d->m_applicationSdk; }

    const std::vector<KMExtension> &getExtensions() { return d->m_extensions; }

    const std::list<std::string> &getShared() { return d->m_contextShared; }

    const std::list<std::string> &getSockets() { return d->m_contextSockets; }

    const std::list<std::string> &getDevices() { return d->m_context_evices; }

    const std::list<std::string> &getFeatures() { return d->m_contextFeatures; }

    const std::list<std::string> &getFilesystem() { return d->m_contextFilesystems; }

    const std::list<std::string> &getPersistent() { return d->m_contextPersistent; }

    const std::list<std::string> &getUnsetEnvironment() { return d->m_contextUnsetEnvironment; }

    const std::map<std::string, std::string> &getSessionBusPolicy() { return d->m_sessionBusPolicy; }

    const std::map<std::string, std::string> &getSystemBusPolicy() { return d->m_systemBusPolicy; }

    const std::map<std::string, std::string> &getEnvironment() { return d->m_environment; }

    const std::map<std::string, std::vector<std::string>> &getGenericPolicy() { return d->m_genericPolicy; }

    const std::list<std::string> &getXDConfPaths() { return d->m_XDConfPaths; }

    const std::string &getXDConfMigratePath() { return d->m_XDConfMigratePath; }

    bool isApp() { return d->m_isApp; }

private:
    void initApplication();
    void initExtensions();
    void initGenericPolicy();
    void initContext();
    void initSessionBusPolicy();
    void initSystemBusPolicy();
    void initEnvironment();
    void initXDConf();

private:
    class Private
    {
    public:
        bool m_isApp = true;

        std::string m_application;
        std::string m_applicationCommand;
        std::string m_applicationName;
        std::string m_applicationRequiredKaiming;
        std::string m_applicationRuntime;
        std::string m_applicationSdk;
        std::list<std::string> m_applicationTags;

        std::vector<KMExtension> m_extensions;

        std::list<std::string> m_contextShared;
        std::list<std::string> m_contextSockets;
        std::list<std::string> m_context_evices;
        std::list<std::string> m_contextFeatures;
        std::list<std::string> m_contextFilesystems;
        std::list<std::string> m_contextPersistent;
        std::list<std::string> m_contextUnsetEnvironment;

        std::map<std::string, std::string> m_sessionBusPolicy;
        std::map<std::string, std::string> m_systemBusPolicy;

        std::map<std::string, std::string> m_environment;

        std::map<std::string, std::vector<std::string>> m_genericPolicy;

        std::list<std::string> m_XDConfPaths;
        std::string m_XDConfMigratePath;
    };

    std::shared_ptr<Private> d;
};

#endif // KMMETADATA_H
