/*
 * Copyright (C) 2022 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 <dirent.h>
#include <dlfcn.h>
#include <media/cas/CasAPI.h>
#include <utils/KeyedVector.h>
#include <utils/Mutex.h>
#include "SharedLibrary.h"

using namespace std;

namespace aidl {
namespace android {
namespace hardware {
namespace cas {

using namespace ::android;

template <class T>
class FactoryLoader {
  public:
    FactoryLoader(const char* name) : mFactory(NULL), mCreateFactoryFuncName(name) {}

    virtual ~FactoryLoader() { closeFactory(); }

    bool findFactoryForScheme(int32_t CA_system_id, shared_ptr<SharedLibrary>* library = NULL,
                              T** factory = NULL);

    bool enumeratePlugins(vector<AidlCasPluginDescriptor>* results);

  private:
    typedef T* (*CreateFactoryFunc)();

    Mutex mMapLock;
    T* mFactory;
    const char* mCreateFactoryFuncName;
    shared_ptr<SharedLibrary> mLibrary;
    KeyedVector<int32_t, String8> mCASystemIdToLibraryPathMap;
    KeyedVector<String8, shared_ptr<SharedLibrary>> mLibraryPathToOpenLibraryMap;

    bool loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id,
                                      shared_ptr<SharedLibrary>* library, T** factory);

    bool queryPluginsFromPath(const String8& path, vector<AidlCasPluginDescriptor>* results);

    bool openFactory(const String8& path);
    void closeFactory();
};

template <class T>
bool FactoryLoader<T>::findFactoryForScheme(int32_t CA_system_id,
                                            shared_ptr<SharedLibrary>* library, T** factory) {
    if (library != NULL) {
        library->reset();
    }
    if (factory != NULL) {
        *factory = NULL;
    }

    Mutex::Autolock autoLock(mMapLock);

    // first check cache
    ssize_t index = mCASystemIdToLibraryPathMap.indexOfKey(CA_system_id);
    if (index >= 0) {
        return loadFactoryForSchemeFromPath(mCASystemIdToLibraryPathMap[index], CA_system_id,
                                            library, factory);
    }

    // no luck, have to search
#ifdef __LP64__
    String8 dirPath("/vendor/lib64/mediacas");
#else
    String8 dirPath("/vendor/lib/mediacas");
#endif
    DIR* pDir = opendir(dirPath.string());

    if (pDir == NULL) {
        ALOGE("Failed to open plugin directory %s", dirPath.string());
        return false;
    }

    struct dirent* pEntry;
    while ((pEntry = readdir(pDir))) {
        String8 pluginPath = dirPath + "/" + pEntry->d_name;
        if (pluginPath.getPathExtension() == ".so") {
            if (loadFactoryForSchemeFromPath(pluginPath, CA_system_id, library, factory)) {
                mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath);
                closedir(pDir);

                return true;
            }
        }
    }

    closedir(pDir);

    ALOGE("Failed to find plugin");
    return false;
}

template <class T>
bool FactoryLoader<T>::enumeratePlugins(vector<AidlCasPluginDescriptor>* results) {
    ALOGI("enumeratePlugins");

    results->clear();

#ifdef __LP64__
    String8 dirPath("/vendor/lib64/mediacas");
#else
    String8 dirPath("/vendor/lib/mediacas");
#endif
    DIR* pDir = opendir(dirPath.string());

    if (pDir == NULL) {
        ALOGE("Failed to open plugin directory %s", dirPath.string());
        return false;
    }

    Mutex::Autolock autoLock(mMapLock);

    struct dirent* pEntry;
    while ((pEntry = readdir(pDir))) {
        String8 pluginPath = dirPath + "/" + pEntry->d_name;
        if (pluginPath.getPathExtension() == ".so") {
            queryPluginsFromPath(pluginPath, results);
        }
    }
    closedir(pDir);
    return true;
}

template <class T>
bool FactoryLoader<T>::loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id,
                                                    shared_ptr<SharedLibrary>* library,
                                                    T** factory) {
    closeFactory();

    if (!openFactory(path) || !mFactory->isSystemIdSupported(CA_system_id)) {
        closeFactory();
        return false;
    }

    if (library != NULL) {
        *library = mLibrary;
    }
    if (factory != NULL) {
        *factory = mFactory;
    }
    return true;
}

template <class T>
bool FactoryLoader<T>::queryPluginsFromPath(const String8& path,
                                            vector<AidlCasPluginDescriptor>* results) {
    closeFactory();

    vector<CasPluginDescriptor> descriptors;
    if (!openFactory(path) || mFactory->queryPlugins(&descriptors) != OK) {
        closeFactory();
        return false;
    }

    for (auto it = descriptors.begin(); it != descriptors.end(); it++) {
        results->push_back(
                AidlCasPluginDescriptor{.caSystemId = it->CA_system_id, .name = it->name.c_str()});
    }
    return true;
}

template <class T>
bool FactoryLoader<T>::openFactory(const String8& path) {
    // get strong pointer to open shared library
    ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path);
    if (index >= 0) {
        mLibrary = mLibraryPathToOpenLibraryMap[index];
    } else {
        index = mLibraryPathToOpenLibraryMap.add(path, NULL);
    }

    if (!mLibrary.get()) {
        mLibrary = ::ndk::SharedRefBase::make<SharedLibrary>(path);
        if (!*mLibrary) {
            return false;
        }

        mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary);
    }

    CreateFactoryFunc createFactory = (CreateFactoryFunc)mLibrary->lookup(mCreateFactoryFuncName);
    if (createFactory == NULL || (mFactory = createFactory()) == NULL) {
        return false;
    }
    return true;
}

template <class T>
void FactoryLoader<T>::closeFactory() {
    delete mFactory;
    mFactory = NULL;
    mLibrary.reset();
}

}  // namespace cas
}  // namespace hardware
}  // namespace android
}  // namespace aidl
