/*
 * Copyright (C) 2010 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 __PLUGIN_MANAGER_H__
#define __PLUGIN_MANAGER_H__

#include <dlfcn.h>
#include <sys/types.h>
#include <dirent.h>

#include <utils/String8.h>
#include <utils/Vector.h>
#include <utils/KeyedVector.h>

#include <filesystem>

namespace android {

const char* const PLUGIN_MANAGER_CREATE = "create";
const char* const PLUGIN_MANAGER_DESTROY = "destroy";
const char* const PLUGIN_EXTENSION = ".so";

/**
 * This is the template class for Plugin manager.
 *
 * The DrmManager uses this class to handle the plugins.
 *
 */
template<typename Type>
class TPlugInManager {
private:
    typedef void*      HANDLE;
    typedef Type*      create_t(void);
    typedef void       destroy_t(Type*);
    typedef create_t*  FPCREATE;
    typedef destroy_t* FPDESTORY;

    typedef struct _PlugInContainer {
        String8   sPath;
        HANDLE    hHandle;
        FPCREATE  fpCreate;
        FPDESTORY fpDestory;
        Type*     pInstance;

        _PlugInContainer():
            sPath("")
            ,hHandle(NULL)
            ,fpCreate(NULL)
            ,fpDestory(NULL)
            ,pInstance(NULL)
            {}
    } PlugInContainer;

    typedef KeyedVector<String8, PlugInContainer*> PlugInMap;
    PlugInMap m_plugInMap;

    typedef Vector<String8> PlugInIdList;
    PlugInIdList m_plugInIdList;

public:
    /**
     * Load all the plug-ins in the specified directory
     *
     * @param[in] rsPlugInDirPath
     *     Directory path which plug-ins (dynamic library) are stored
     * @note Plug-ins should be implemented according to the specification
     */
    void loadPlugIns(const String8& rsPlugInDirPath) {
        Vector<String8> plugInFileList = getPlugInPathList(rsPlugInDirPath);

        if (!plugInFileList.isEmpty()) {
            for (size_t i = 0; i < plugInFileList.size(); ++i) {
                loadPlugIn(plugInFileList[i]);
            }
        }
    }

    /**
     * Unload all the plug-ins
     *
     */
    void unloadPlugIns() {
        for (size_t i = 0; i < m_plugInIdList.size(); ++i) {
            unloadPlugIn(m_plugInIdList[i]);
        }
        m_plugInIdList.clear();
    }

    /**
     * Get all the IDs of available plug-ins
     *
     * @return[in] plugInIdList
     *     String type Vector in which all plug-in IDs are stored
     */
    Vector<String8> getPlugInIdList() const {
        return m_plugInIdList;
    }

    /**
     * Get a plug-in reference of specified ID
     *
     * @param[in] rsPlugInId
     *     Plug-in ID to be used
     * @return plugIn
     *     Reference of specified plug-in instance
     */
    Type& getPlugIn(const String8& rsPlugInId) {
        if (!contains(rsPlugInId)) {
            // This error case never happens
        }
        return *(m_plugInMap.valueFor(rsPlugInId)->pInstance);
    }

public:
    /**
     * Load a plug-in stored in the specified path
     *
     * @param[in] rsPlugInPath
     *     Plug-in (dynamic library) file path
     * @note Plug-in should be implemented according to the specification
     */
    void loadPlugIn(const String8& rsPlugInPath) {
        if (contains(rsPlugInPath)) {
            return;
        }

        PlugInContainer* pPlugInContainer = new PlugInContainer();

        pPlugInContainer->hHandle = dlopen(rsPlugInPath.c_str(), RTLD_LAZY);

        if (NULL == pPlugInContainer->hHandle) {
            delete pPlugInContainer;
            pPlugInContainer = NULL;
            return;
        }

        pPlugInContainer->sPath = rsPlugInPath;
        pPlugInContainer->fpCreate
                = (FPCREATE)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_CREATE);
        pPlugInContainer->fpDestory
                = (FPDESTORY)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_DESTROY);

        if (NULL != pPlugInContainer->fpCreate && NULL != pPlugInContainer->fpDestory) {
            pPlugInContainer->pInstance = (Type*)pPlugInContainer->fpCreate();
            m_plugInIdList.add(rsPlugInPath);
            m_plugInMap.add(rsPlugInPath, pPlugInContainer);
        } else {
            dlclose(pPlugInContainer->hHandle);
            delete pPlugInContainer;
            pPlugInContainer = NULL;
            return;
        }
    }

    /**
     * Unload a plug-in stored in the specified path
     *
     * @param[in] rsPlugInPath
     *     Plug-in (dynamic library) file path
     */
    void unloadPlugIn(const String8& rsPlugInPath) {
        if (!contains(rsPlugInPath)) {
            return;
        }

        PlugInContainer* pPlugInContainer = m_plugInMap.valueFor(rsPlugInPath);
        pPlugInContainer->fpDestory(pPlugInContainer->pInstance);
        dlclose(pPlugInContainer->hHandle);

        m_plugInMap.removeItem(rsPlugInPath);
        delete pPlugInContainer;
        pPlugInContainer = NULL;
    }

private:
    /**
     * True if TPlugInManager contains rsPlugInId
     */
    bool contains(const String8& rsPlugInId) {
        return m_plugInMap.indexOfKey(rsPlugInId) != NAME_NOT_FOUND;
    }

    /**
     * Return file path list of plug-ins stored in the specified directory
     *
     * @param[in] rsDirPath
     *     Directory path in which plug-ins are stored
     * @return plugInFileList
     *     String type Vector in which file path of plug-ins are stored
     */
    Vector<String8> getPlugInPathList(const String8& rsDirPath) {
        Vector<String8> fileList;
        DIR* pDir = opendir(rsDirPath.c_str());
        struct dirent* pEntry;

        while (NULL != pDir && NULL != (pEntry = readdir(pDir))) {
            if (!isPlugIn(pEntry)) {
                continue;
            }
            String8 plugInPath;
            plugInPath += rsDirPath;
            plugInPath += "/";
            plugInPath += pEntry->d_name;

            fileList.add(plugInPath);
        }

        if (NULL != pDir) {
            closedir(pDir);
        }

        return fileList;
    }

    /**
     * True if the input name denotes plug-in
     */
    bool isPlugIn(const struct dirent* pEntry) const {
        const auto extension = std::filesystem::path(pEntry->d_name).extension();
        // Note that the plug-in extension must exactly match case
        return extension.string() == PLUGIN_EXTENSION;
    }

    /**
     * True if input entry is directory
     */
    bool isDirectory(const struct dirent* pEntry) const {
        return DT_DIR == pEntry->d_type;
    }

    /**
     * True if input entry is regular file
     */
    bool isRegularFile(const struct dirent* pEntry) const {
        return DT_REG == pEntry->d_type;
    }

    /**
     * True if input entry is link
     */
    bool isLink(const struct dirent* pEntry) const {
        return DT_LNK == pEntry->d_type;
    }
};

};

#endif /* __PLUGIN_MANAGER_H__ */

