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

#define LOG_TAG "CtsSampleNativeService"

#include "NativeService.h"

#include <android/binder_ibinder.h>
#include <dlfcn.h>
#include <inttypes.h>
#include <log/log.h>
#include <unistd.h>

#include <map>

#include "PreloadedLibrary.h"

#define ASSERT(a, ret)                                             \
    do {                                                           \
        if (!(a)) {                                                \
            ALOGE("Failure: %s at %s:%d", #a, __FILE__, __LINE__); \
            return (ret);                                          \
        }                                                          \
    } while (0)

#define ASSERT_VOID(a)                                             \
    do {                                                           \
        if (!(a)) {                                                \
            ALOGE("Failure: %s at %s:%d", #a, __FILE__, __LINE__); \
            return;                                                \
        }                                                          \
    } while (0)

enum class ServiceBindingState {
    kBound,
    kUnbound,
    kRebound,
};

struct ServiceBinding {
    ServiceBindingState mState;
    uint64_t mToken;
    std::string mIntentAction;
    std::shared_ptr<NativeServiceWrapper> mWrapper;

    ServiceBinding(uint64_t token, const char* action,
                   std::shared_ptr<NativeServiceWrapper> wrapper)
          : mState(ServiceBindingState::kBound),
            mToken(token),
            mIntentAction(action),
            mWrapper(wrapper) {}
};

// This map doesn't have to be guarded by a mutex because it's only accessed in
// native service callbacks and they are serialized in the main thread looper.
static std::map<ANativeService*, std::map<uint64_t, ServiceBinding>> gBindingMap;

ndk::ScopedAStatus NativeServiceWrapper::registerListener(
        const std::shared_ptr<INativeServiceListener>& listener) {
    std::lock_guard<std::mutex> lock(mutex_);
    listeners_.insert(listener);
    listener->onRegister();
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus NativeServiceWrapper::isLibraryMarkedPreloaded(bool* result) {
    *result = isMarkedPreloaded();
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus NativeServiceWrapper::getParentPid(int* result) {
    *result = getppid();
    return ndk::ScopedAStatus::ok();
}

void NativeServiceWrapper::doUnbind() {
    std::lock_guard<std::mutex> lock(mutex_);
    for (const auto& listener : listeners_) {
        listener->onUnbind();
    }
}

void NativeServiceWrapper::doRebind() {
    std::lock_guard<std::mutex> lock(mutex_);
    for (const auto& listener : listeners_) {
        listener->onRebind();
    }
}

extern "C" void native_service_onDestroy(ANativeService* _Nonnull service) {
    ALOGI("native_service_onDestroy – service %p", service);

    auto itr = gBindingMap.find(service);
    ASSERT_VOID(itr != gBindingMap.end());

    gBindingMap.erase(itr);
}

extern "C" AIBinder* native_service_onBind(ANativeService* _Nonnull service, uint64_t bindToken,
                                           char const* _Nullable action,
                                           char const* _Nullable data) {
    ALOGI("native_service_onBind – service %p, bindToken %" PRIu64 ", action: %s, data %s", service,
          bindToken, action, data);

    std::shared_ptr<NativeServiceWrapper> wrapper;

    if (gBindingMap.find(service) != gBindingMap.end() &&
        gBindingMap[service].find(bindToken) != gBindingMap[service].end()) {
        auto& conn = gBindingMap[service].find(bindToken)->second;
        ASSERT(conn.mState == ServiceBindingState::kUnbound, nullptr);
        wrapper = conn.mWrapper;
        conn.mState = ServiceBindingState::kBound;
    } else {
        wrapper = ndk::SharedRefBase::make<NativeServiceWrapper>();
        gBindingMap[service].emplace(bindToken, ServiceBinding(bindToken, action, wrapper));
    }

    auto binder = wrapper->asBinder();
    AIBinder_incStrong(binder.get());

    ASSERT(action != nullptr, nullptr);
    auto actionStr = std::string(action);
    ASSERT(actionStr == "TEST_ACTION 🂡 🂢 🂣" || actionStr == "TEST_ACTION_NOREBIND" ||
                   actionStr == "TEST_ACTION_REBIND" || actionStr == "TEST_ACTION_KEEPALIVE",
           nullptr);
    if (actionStr == "TEST_ACTION_KEEPALIVE") {
        ASSERT(data == nullptr, nullptr);
    } else {
        ASSERT(std::string(data) ==
                       R"(content://com.example/people/%F0%9F%82%A1%20%F0%9F%82%A2%20%F0%9F%82%A3)",
               nullptr);
    }

    return binder.get();
}

extern "C" void native_service_onRebind(ANativeService* _Nonnull service, uint64_t bindToken) {
    ALOGI("native_service_onRebind – service %p, bindToken %" PRIu64, service, bindToken);

    auto itr = gBindingMap.find(service);
    ASSERT_VOID(itr != gBindingMap.end());

    auto bindingItr = itr->second.find(bindToken);
    ASSERT_VOID(bindingItr != itr->second.end());
    ASSERT_VOID(bindingItr->second.mState == ServiceBindingState::kUnbound);

    bindingItr->second.mState = ServiceBindingState::kRebound;

    auto wrapper = bindingItr->second.mWrapper;
    wrapper->doRebind();
}

extern "C" bool native_service_onUnbind(ANativeService* _Nonnull service, uint64_t bindToken) {
    ALOGI("native_service_onUnbind – service %p, bindToken %" PRIu64, service, bindToken);

    bool res = false;

    auto itr = gBindingMap.find(service);
    ASSERT(itr != gBindingMap.end(), false);

    auto bindingItr = itr->second.find(bindToken);
    ASSERT(bindingItr != itr->second.end(), false);
    ASSERT(bindingItr->second.mState == ServiceBindingState::kBound ||
                   bindingItr->second.mState == ServiceBindingState::kRebound,
           false);

    bindingItr->second.mState = ServiceBindingState::kUnbound;
    if (bindingItr->second.mIntentAction == "TEST_ACTION_REBIND") {
        res = true;
    }

    auto wrapper = bindingItr->second.mWrapper;
    wrapper->doUnbind();

    ALOGI("native_service_onUnbind – res %d", res);
    return res;
}

extern "C" void native_service_onTrimMemory(ANativeService* _Nonnull service,
                                            ANativeServiceTrimMemoryLevel level) {
    ALOGI("native_service_onTrimMemory – service %p, level %d", service, level);
}

extern "C" void native_service_createService(ANativeService* service) {
    ALOGI("native_service_createService – service %p", service);

    ANativeService_setOnBindCallback(service, native_service_onBind);
    ANativeService_setOnUnbindCallback(service, native_service_onUnbind);
    ANativeService_setOnRebindCallback(service, native_service_onRebind);
    ANativeService_setOnDestroyCallback(service, native_service_onDestroy);
    ANativeService_setOnTrimMemoryCallback(service, native_service_onTrimMemory);
}
