/*
 * 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.
 */

#include <gapir/context.h>
#include <gapir/memory_manager.h>
#include <gapir/resource_disk_cache.h>
#include <gapir/resource_in_memory_cache.h>
#include <gapir/resource_requester.h>
#include <gapir/server_connection.h>
#include <gapir/server_listener.h>

#include <gapic/connection.h>
#include <gapic/log.h>
#include <gapic/socket_connection.h>
#include <gapic/supported_abis.h>
#include <gapic/target.h>

#include <memory>
#include <stdlib.h>
#include <string.h>

#if TARGET_OS == GAPID_OS_ANDROID
#include <android_native_app_glue.h>
#endif  // TARGET_OS == GAPID_OS_ANDROID

using namespace gapic;
using namespace gapir;

namespace {

std::vector<uint32_t> memorySizes{
    2 * 1024 * 1024 * 1024U,  // 2GB
    1 * 1024 * 1024 * 1024U,  // 1GB
         512 * 1024 * 1024U,  // 512MB
         256 * 1024 * 1024U,  // 256MB
         128 * 1024 * 1024U,  // 128MB
};

// createResourceProvider constructs and returns a ResourceInMemoryCache.
// If cachePath is non-null then the ResourceInMemoryCache will be backed by a
// disk-cache.
std::unique_ptr<ResourceInMemoryCache> createResourceProvider(
        const char* cachePath, MemoryManager* memoryManager) {
    if (cachePath != nullptr) {
        GAPID_FATAL("Disk cache is currently out of service. Got %s", cachePath);
        return std::unique_ptr<ResourceInMemoryCache>(
            ResourceInMemoryCache::create(
                ResourceDiskCache::create(ResourceRequester::create(), cachePath),
                memoryManager->getBaseAddress()));
    } else {
        return std::unique_ptr<ResourceInMemoryCache>(
            ResourceInMemoryCache::create(
                ResourceRequester::create(), memoryManager->getBaseAddress()));
    }
}

void listenConnections(std::unique_ptr<Connection> conn,
                       const char* authToken,
                       const char* cachePath,
                       int idleTimeoutMs,
                       MemoryManager* memoryManager) {
    ServerListener listener(std::move(conn), memoryManager->getSize());

    std::unique_ptr<ResourceInMemoryCache> resourceProvider(
            createResourceProvider(cachePath, memoryManager));

    while (true) {
        std::unique_ptr<ServerConnection> acceptedConn(
                listener.acceptConnection(idleTimeoutMs, authToken));
        if (!acceptedConn) {
            GAPID_INFO("Shutting down");
            break;
        }

        std::unique_ptr<Context> context =
                Context::create(*acceptedConn, resourceProvider.get(), memoryManager);
        if (context == nullptr) {
            GAPID_WARNING("Loading Context failed!");
            continue;
        }

        context->prefetch(resourceProvider.get());

        if (!context->interpret()) {
          GAPID_DEBUG("Interpret returned false");
        }
    }
}

}  // anonymous namespace

#if TARGET_OS == GAPID_OS_ANDROID
// Main function for android
void android_main(struct android_app* app) {
    app_dummy();
    MemoryManager memoryManager(memorySizes);
    auto conn = SocketConnection::createPipe("gapir", "");
    if (conn == nullptr) {
        GAPID_FATAL("Failed to create abstract local port: gapir");
    }

    __android_log_print(ANDROID_LOG_DEBUG, "GAPIR",
            "Started Graphics API Replay daemon.\n"
            "Listening on localabstract port 'gapir'\n"
            "Supported ABIs: %s\n", gapic::supportedABIs());

    // Note if you want to create a disk cache create it under:
    // app->activity->internalDataPath
    listenConnections(std::move(conn), nullptr, nullptr, Connection::NO_TIMEOUT, &memoryManager);
}

#else  // TARGET_OS == GAPID_OS_ANDROID
// Main function for PC
int main(int argc, const char* argv[]) {
    const char* logPath = "logs/gapir.log";

    const char* cachePath = nullptr;
    const char* portStr = "0";
    const char* authToken = nullptr;
    int idleTimeoutMs = Connection::NO_TIMEOUT;

    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "--auth-token") == 0) {
            if (i + 1 >= argc) {
                GAPID_FATAL("Usage: --auth-token <token-string>");
            }
            authToken = argv[++i];
        } else if (strcmp(argv[i], "--cache") == 0) {
            if (i + 1 >= argc) {
                GAPID_FATAL("Usage: --cache <cache-directory>");
            }
            cachePath = argv[++i];
        } else if (strcmp(argv[i], "--port") == 0) {
            if (i + 1 >= argc) {
                GAPID_FATAL("Usage: --port <port_num>");
            }
            portStr = argv[++i];
        } else if (strcmp(argv[i], "--log") == 0) {
            if (i + 1 >= argc) {
                GAPID_FATAL("Usage: --log <log-file-path>");
            }
            logPath = argv[++i];
        } else if (strcmp(argv[i], "--idle-timeout-ms") == 0) {
            if (i + 1 >= argc) {
                GAPID_FATAL("Usage: --idle-timeout-ms <timeout in milliseconds>");
            }
            idleTimeoutMs = atoi(argv[++i]);
        } else {
            GAPID_FATAL("Unknown argument: %s", argv[i]);
        }
    }

    GAPID_LOGGER_INIT(logPath);

    MemoryManager memoryManager(memorySizes);
    GAPID_INFO("gapir listening on port %s", portStr);
    auto conn = SocketConnection::createSocket("127.0.0.1", portStr);
    if (conn == nullptr) {
        GAPID_FATAL("Failed to create listening socket on port: %s", portStr);
    }
    listenConnections(std::move(conn), authToken, cachePath, idleTimeoutMs, &memoryManager);
    return EXIT_SUCCESS;
}

#endif  // TARGET_OS == GAPID_OS_ANDROID
