/*
 * Copyright © 2011 Linaro Limited
 * Copyright © 2011 0xlab - http://0xlab.org/
 *
 * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
 *
 * glmark2 is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * glmark2.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *  Alexandros Frantzis (glmark2)
 *  Jim Huang (Strict JNI registration using JNI_OnLoad())
 */
#include <assert.h>
#include <jni.h>
#include <vector>
#include <string>
#include <fstream>
#include "canvas-android.h"
#include "benchmark.h"
#include "options.h"
#include "log.h"
#include "util.h"
#include "main-loop.h"
#include "benchmark-collection.h"

static Canvas *g_canvas;
static MainLoop *g_loop;
static BenchmarkCollection *g_benchmark_collection;
static std::ostream *g_log_extra;

class MainLoopAndroid : public MainLoop
{
public:
    MainLoopAndroid(Canvas &canvas, const std::vector<Benchmark *> &benchmarks) :
        MainLoop(canvas, benchmarks) {}

    virtual void log_scene_info() {}

    virtual void log_scene_result()
    {
        if (scene_setup_status_ == SceneSetupStatusSuccess) {
            Log::info("%s FPS: %u FrameTime: %.3f ms\n",
                      scene_->info_string().c_str(),
                      scene_->average_fps(),
                      1000.0 / scene_->average_fps());
        }
        else if (scene_setup_status_ == SceneSetupStatusUnsupported) {
            Log::info("%s Unsupported\n",
                      scene_->info_string().c_str());
        }
        else {
            Log::info("%s Set up failed\n",
                      scene_->info_string().c_str());
        }
    }
};

class MainLoopDecorationAndroid : public MainLoopDecoration
{
public:
    MainLoopDecorationAndroid(Canvas &canvas, const std::vector<Benchmark *> &benchmarks) :
        MainLoopDecoration(canvas, benchmarks) {}

    virtual void log_scene_info() {}

    virtual void log_scene_result()
    {
        if (scene_setup_status_ == SceneSetupStatusSuccess) {
            Log::info("%s FPS: %u FrameTime: %.3f ms\n",
                      scene_->info_string().c_str(),
                      scene_->average_fps(),
                      1000.0 / scene_->average_fps());
        }
        else if (scene_setup_status_ == SceneSetupStatusUnsupported) {
            Log::info("%s Unsupported\n",
                      scene_->info_string().c_str());
        }
        else {
            Log::info("%s Set up failed\n",
                      scene_->info_string().c_str());
        }
    }
};

/** 
 * Converts an std::vector containing arguments to argc,argv.
 */
static void
arg_vector_to_argv(const std::vector<std::string> &arguments, int &argc, char **&argv)
{
    argc = arguments.size() + 1;
    argv = new char* [argc];
    argv[0] = strdup("glmark2");

    for (unsigned int i = 0; i < arguments.size(); i++)
        argv[i + 1] = strdup(arguments[i].c_str());
}

/** 
 * Populates the command line arguments from the arguments file.
 * 
 * @param argc the number of arguments
 * @param argv the argument array
 */
static void
get_args_from_file(const std::string &arguments_file, int &argc, char **&argv)
{
    std::vector<std::string> arguments;
    std::ifstream ifs(arguments_file.c_str());

    if (!ifs.fail()) {
        std::string line;
        while (getline(ifs, line)) {
            if (!line.empty())
                Util::split(line, ' ', arguments, Util::SplitModeQuoted);
        }
    }

    arg_vector_to_argv(arguments, argc, argv);
}

/** 
 * Populates the command line arguments from the arguments file.
 * 
 * @param argc the number of arguments
 * @param argv the argument array
 */
static void
get_args_from_string(const std::string &args_str, int &argc, char **&argv)
{
    std::vector<std::string> arguments;
    Util::split(args_str, ' ', arguments, Util::SplitModeQuoted);

    arg_vector_to_argv(arguments, argc, argv);
}

/** 
 * Releases the command line arguments.
 * 
 * @param argc the number of arguments
 * @param argv the argument array
 */
static void
release_args(int argc, char **argv)
{
    for (int i = 0; i < argc; i++)
        free(argv[i]);

    delete[] argv;
}

/** 
 * Converts a GLVisualConfig Java object to a GLVisualConfig C++ object.
 * 
 * @param env the JNIEnv
 * @param jvc the Java VisualConfig object to convert
 * @param vc the C++ VisualConfig object to fill
 */
static void
gl_visual_config_from_jobject(JNIEnv *env, jobject jvc, GLVisualConfig &vc)
{
    jclass cls = env->GetObjectClass(jvc);
    jfieldID fid;

    fid = env->GetFieldID(cls, "red", "I");
    vc.red = env->GetIntField(jvc, fid);

    fid = env->GetFieldID(cls, "green", "I");
    vc.green = env->GetIntField(jvc, fid);
    
    fid = env->GetFieldID(cls, "blue", "I");
    vc.blue = env->GetIntField(jvc, fid);

    fid = env->GetFieldID(cls, "alpha", "I");
    vc.alpha = env->GetIntField(jvc, fid);

    fid = env->GetFieldID(cls, "depth", "I");
    vc.depth = env->GetIntField(jvc, fid);

    fid = env->GetFieldID(cls, "buffer", "I");
    vc.buffer = env->GetIntField(jvc, fid);
}

/** 
 * Creates a SceneInfo Java object from a Scene.
 * 
 * @param env the JNIEnv
 */
static jobject
scene_info_from_scene(JNIEnv *env, Scene &scene)
{
    jclass cls = env->FindClass("org/linaro/glmark2/SceneInfo");
    jmethodID constructor = env->GetMethodID(cls, "<init>", "(Ljava/lang/String;)V");
    jmethodID add_option = env->GetMethodID(cls, "addOption", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V");

    /* Create the SceneInfo object */
    jstring name = env->NewStringUTF(scene.name().c_str());
    jobject scene_info = env->NewObject(cls, constructor, name);

    const std::map<std::string, Scene::Option> &options = scene.options();

    /* Add options to the SceneInfo object */
    for (std::map<std::string, Scene::Option>::const_iterator opt_iter = options.begin();
         opt_iter != options.end();
         opt_iter++)
    {
        const Scene::Option &opt = opt_iter->second;
        jstring opt_name = env->NewStringUTF(opt.name.c_str());
        jstring opt_description = env->NewStringUTF(opt.description.c_str());
        jstring opt_default_value = env->NewStringUTF(opt.default_value.c_str());

        /* Create and populate the acceptable values array */
        jclass string_cls = env->FindClass("java/lang/String");
        jobjectArray opt_acceptable_values = env->NewObjectArray(opt.acceptable_values.size(),
                                                                 string_cls, 0);
        
        for (size_t i = 0; i < opt.acceptable_values.size(); i++) {
            jstring opt_value = env->NewStringUTF(opt.acceptable_values[i].c_str());
            env->SetObjectArrayElement(opt_acceptable_values, i, opt_value);
            env->DeleteLocalRef(opt_value);
        }

        env->CallVoidMethod(scene_info, add_option,
                            opt_name,
                            opt_description,
                            opt_default_value,
                            opt_acceptable_values);

        env->DeleteLocalRef(opt_name);
        env->DeleteLocalRef(opt_description);
        env->DeleteLocalRef(opt_default_value);
        env->DeleteLocalRef(opt_acceptable_values);
    }

    return scene_info;
}

class DummyCanvas : public Canvas {
public:
    DummyCanvas() : Canvas(0, 0) {}
};

/** 
 * Creates all the available scenes and adds them to the supplied vector.
 * 
 * @param scenes the vector to add the scenes to
 * @param canvas the canvas to create the scenes with
 */
static void
create_and_add_scenes(std::vector<Scene*>& scenes, Canvas& canvas)
{
    scenes.push_back(new SceneDefaultOptions(canvas));
    scenes.push_back(new SceneBuild(canvas));
    scenes.push_back(new SceneTexture(canvas));
    scenes.push_back(new SceneShading(canvas));
    scenes.push_back(new SceneConditionals(canvas));
    scenes.push_back(new SceneFunction(canvas));
    scenes.push_back(new SceneLoop(canvas));
    scenes.push_back(new SceneBump(canvas));
    scenes.push_back(new SceneEffect2D(canvas));
    scenes.push_back(new ScenePulsar(canvas));
    scenes.push_back(new SceneDesktop(canvas));
    scenes.push_back(new SceneBuffer(canvas));
    scenes.push_back(new SceneIdeas(canvas));
    scenes.push_back(new SceneTerrain(canvas));
    scenes.push_back(new SceneJellyfish(canvas));
    scenes.push_back(new SceneShadow(canvas));
    scenes.push_back(new SceneRefract(canvas));
}


void
Java_org_linaro_glmark2_native_init(JNIEnv* env, jclass clazz,
                                    jobject asset_manager,
                                    jstring args,
                                    jstring log_file)
{
    static_cast<void>(clazz);
    static const std::string arguments_file("/data/glmark2/args");
    int argc = 0;
    char **argv = 0;

    /* Load arguments from argument string or arguments file and parse them */
    if (args) {
        if (env->GetStringUTFLength(args) > 0) {
            const char *args_c_str = env->GetStringUTFChars(args, 0);
            if (args_c_str) {
                get_args_from_string(std::string(args_c_str), argc, argv);
                env->ReleaseStringUTFChars(args, args_c_str);
            }
        }
    }
    else {
        get_args_from_file(arguments_file, argc, argv);
    }

    Options::parse_args(argc, argv);
    release_args(argc, argv);

    /* Get the log file path and open the log file */
    const char *log_file_c_str = env->GetStringUTFChars(log_file, 0);
    if (log_file_c_str) {
        g_log_extra = new std::ofstream(log_file_c_str, std::ios::binary);
        env->ReleaseStringUTFChars(log_file, log_file_c_str);
    }

    /* Force reuse of EGL/GL context */
    Options::reuse_context = true;

    Log::init("glmark2", Options::show_debug, g_log_extra);
    Util::android_set_asset_manager(AAssetManager_fromJava(env, asset_manager));

    g_canvas = new CanvasAndroid(100, 100);
    g_canvas->init();

    Log::info("glmark2 %s\n", GLMARK_VERSION);
    g_canvas->print_info();

    std::vector<Scene*> scenes;

    /* Add and register scenes */
    create_and_add_scenes(scenes, *g_canvas);

    for (std::vector<Scene*>::const_iterator iter = scenes.begin();
         iter != scenes.end();
         iter++)
    {
        Benchmark::register_scene(**iter);
    }

    g_benchmark_collection = new BenchmarkCollection();
    g_benchmark_collection->populate_from_options();

    if (g_benchmark_collection->needs_decoration()) {
        g_loop = new MainLoopDecorationAndroid(*g_canvas,
                                               g_benchmark_collection->benchmarks());
    }
    else {
        g_loop = new MainLoopAndroid(*g_canvas,
                                     g_benchmark_collection->benchmarks());
    }
}

void
Java_org_linaro_glmark2_native_resize(JNIEnv* env,
                                      jclass clazz,
                                      jint w,
                                      jint h)
{
    static_cast<void>(env);
    static_cast<void>(clazz);

    Log::debug("Resizing to %d x %d\n", w, h);
    g_canvas->resize(w, h);
}

void
Java_org_linaro_glmark2_native_done(JNIEnv* env)
{
    static_cast<void>(env);

    delete g_loop;
    delete g_benchmark_collection;
    delete g_canvas;
    delete g_log_extra;
}

jboolean
Java_org_linaro_glmark2_native_render(JNIEnv* env)
{
    static_cast<void>(env);

    if (!g_loop->step()) {
        Log::info("glmark2 Score: %u\n", g_loop->score());
        return false;
    }

    return true;
}

jint
Java_org_linaro_glmark2_native_scoreConfig(JNIEnv* env, jclass clazz,
                                           jobject jvc, jobject jtarget)
{
    static_cast<void>(clazz);

    GLVisualConfig vc;
    GLVisualConfig target;

    gl_visual_config_from_jobject(env, jvc, vc);
    gl_visual_config_from_jobject(env, jtarget, target);

    return vc.match_score(target);
}

jobjectArray
Java_org_linaro_glmark2_native_getSceneInfo(JNIEnv* env, jclass clazz,
                                            jobject asset_manager)
{
    static_cast<void>(clazz);

    Util::android_set_asset_manager(AAssetManager_fromJava(env, asset_manager));

    std::vector<Scene*> scenes;
    DummyCanvas canvas;
    std::vector<jobject> si_vector;

    create_and_add_scenes(scenes, canvas);

    /* Create SceneInfo instances for all the scenes */
    for (std::vector<Scene*>::const_iterator iter = scenes.begin();
         iter != scenes.end();
         iter++)
    {
        jobject si = scene_info_from_scene(env, **iter);
        si_vector.push_back(si);
    }

    /* Create a SceneInfo[] array */
    jclass si_cls = env->FindClass("org/linaro/glmark2/SceneInfo");
    jobjectArray si_array = env->NewObjectArray(si_vector.size(), si_cls, 0);
    
    /* Populate the SceneInfo[] array */
    for (size_t i = 0; i < si_vector.size(); i++)
        env->SetObjectArrayElement(si_array, i, si_vector[i]);

    Util::dispose_pointer_vector(scenes);

    return si_array;
}

static JNINativeMethod glmark2_native_methods[] = {
    {
        "init",
        "(Landroid/content/res/AssetManager;Ljava/lang/String;Ljava/lang/String;)V",
        reinterpret_cast<void*>(Java_org_linaro_glmark2_native_init)
    },
    {
        "resize",
        "(II)V",
        reinterpret_cast<void*>(Java_org_linaro_glmark2_native_resize)
    },
    {
        "done",
        "()V",
        reinterpret_cast<void*>(Java_org_linaro_glmark2_native_done)
    },
    {
        "render",
        "()Z",
        reinterpret_cast<void*>(Java_org_linaro_glmark2_native_render)
    },
    {
        "scoreConfig",
        "(Lorg/linaro/glmark2/GLVisualConfig;Lorg/linaro/glmark2/GLVisualConfig;)I",
        reinterpret_cast<void*>(Java_org_linaro_glmark2_native_scoreConfig)
    },
    {
        "getSceneInfo",
        "(Landroid/content/res/AssetManager;)[Lorg/linaro/glmark2/SceneInfo;",
        reinterpret_cast<void*>(Java_org_linaro_glmark2_native_getSceneInfo)
    }
};

static int
register_native_methods(JNIEnv* env, const char* className,
                        JNINativeMethod* gMethods, int numMethods)
{
    jclass clazz;

    clazz = env->FindClass(className);
    if (clazz == NULL) {
        Log::error("Native registration unable to find class '%s'\n",
                   className);
        return JNI_FALSE;
    }
    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
        Log::error("RegisterNatives failed for '%s'\n", className);
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

static int
register_natives(JNIEnv *env)
{
    const char* const class_path_name = "org/linaro/glmark2/Glmark2Native";
    return register_native_methods(env, class_path_name,
                                   glmark2_native_methods,
                                   sizeof(glmark2_native_methods) /
                                   sizeof(glmark2_native_methods[0]));
}

/*
 * Returns the JNI version on success, -1 on failure.
 */
extern "C" jint
JNI_OnLoad(JavaVM* vm, void* reserved)
{
    static_cast<void>(reserved);
    JNIEnv* env = NULL;
    jint result = -1;

    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_4) != JNI_OK) {
        Log::error("JNI_OnLoad: GetEnv failed\n");
        goto bail;
    }
    assert(env != NULL);

    if (!register_natives(env)) {
        Log::error("JNI_OnLoad: glmark2 native registration failed\n");
        goto bail;
    }

    /* success -- return valid version number */
    result = JNI_VERSION_1_4;

bail:
    return result;
}
