/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 */

#include <android_native_app_glue.h>

#include "SkApplication.h"
#include "VisualBench.h"

/**
 * Shared state for our app.
 */
enum State {
    kInit_State,
    kAnimate_State,
    kDestroyRequested_State,
    kFinished_State,
};

struct VisualBenchState {
    VisualBenchState() : fApp(nullptr), fWindow(nullptr), fState(kInit_State) {}
    struct android_app* fApp;
    SkOSWindow* fWindow;
    SkTArray<SkString> fFlags;
    State fState;
};

static void handle_cmd(struct android_app* app, int32_t cmd) {
    struct VisualBenchState* state = (struct VisualBenchState*)app->userData;
    switch (cmd) {
        case APP_CMD_INIT_WINDOW:
            // The window is being shown, get it ready.
            if (state->fApp->window != nullptr && kInit_State == state->fState) {
                // drain any events that occurred before |window| was assigned.
                while (SkEvent::ProcessEvent());

                // Start normal Skia sequence
                application_init();

                SkTArray<const char*> args;
                args.push_back("VisualBench");
                for (int i = 0; i < state->fFlags.count(); i++) {
                    SkDebugf(state->fFlags[i].c_str());
                    args.push_back(state->fFlags[i].c_str());
                }

                state->fWindow = create_sk_window((void*)state->fApp->window,
                                                  args.count(),
                                                  const_cast<char**>(args.begin()));
                state->fWindow->forceInvalAll();
                state->fState = kAnimate_State;
            }
            break;
        case APP_CMD_TERM_WINDOW:
            state->fState = kDestroyRequested_State;
            break;
    }
}

void android_main(struct android_app* state) {
    struct VisualBenchState visualBenchState;

    // Make sure glue isn't stripped.
    app_dummy();

    state->userData = &visualBenchState;
    state->onAppCmd = handle_cmd;
    visualBenchState.fApp = state;

    // Get command line arguments
    JavaVM* jvm = state->activity->vm;
    JNIEnv *env;
    jvm->AttachCurrentThread(&env, 0);

    jobject me = state->activity->clazz;

    jclass acl = env->GetObjectClass(me); //class pointer of NativeActivity
    jmethodID giid = env->GetMethodID(acl, "getIntent", "()Landroid/content/Intent;");
    jobject intent = env->CallObjectMethod(me, giid); //Got our intent

    jclass icl = env->GetObjectClass(intent); //class pointer of Intent
    jmethodID gseid = env->GetMethodID(icl, "getStringExtra",
                                       "(Ljava/lang/String;)Ljava/lang/String;");

    jstring jsParam1 = (jstring)env->CallObjectMethod(intent, gseid,
                                                      env->NewStringUTF("cmdLineFlags"));
    if (jsParam1) {
        const char* flags = env->GetStringUTFChars(jsParam1, 0);
        SkStrSplit(flags, " ", &visualBenchState.fFlags);
        env->ReleaseStringUTFChars(jsParam1, flags);
    }
    jvm->DetachCurrentThread();

    while (1) {
        // Read all pending events.
        int ident;
        int events;
        struct android_poll_source* source;

        // We loop until all events are read, then continue to draw the next frame of animation.
        while ((ident=ALooper_pollAll(0, nullptr, &events, (void**)&source)) >= 0) {
            // Process this event.
            if (source != nullptr) {
                source->process(state, source);
            }

            // Check if we are exiting.
            if (state->destroyRequested != 0) {
                return;
            }

        }

        if (visualBenchState.fWindow) {
            if (visualBenchState.fWindow->destroyRequested()) {
                visualBenchState.fState = kDestroyRequested_State;
            } else {
                visualBenchState.fWindow->update(nullptr);
            }
        }

        if (kDestroyRequested_State == visualBenchState.fState) {
            delete visualBenchState.fWindow;
            visualBenchState.fWindow = nullptr;
            application_term();
            ANativeActivity_finish(state->activity);
            visualBenchState.fState = kFinished_State;
        }
    }
}
