/*
 * Copyright 2012, The Android Open Source Project
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "GeolocationServiceBridge.h"

#include "WebViewCore.h"

#include <GeolocationError.h>
#include <GeolocationPosition.h>
#include <JNIHelp.h>

using JSC::Bindings::getJNIEnv;
using WebCore::GeolocationError;
using WebCore::GeolocationPosition;

namespace android {

static const char* javaGeolocationServiceClassName = "android/webkit/GeolocationService";
enum javaGeolocationServiceClassMethods {
    GeolocationServiceMethodInit = 0,
    GeolocationServiceMethodStart,
    GeolocationServiceMethodStop,
    GeolocationServiceMethodSetEnableGps,
    GeolocationServiceMethodCount,
};
static jmethodID javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodCount];

static const JNINativeMethod javaGeolocationServiceClassNativeMethods[] = {
    { "nativeNewLocationAvailable", "(JLandroid/location/Location;)V",
        (void*) GeolocationServiceBridge::newLocationAvailable },
    { "nativeNewErrorAvailable", "(JLjava/lang/String;)V",
        (void*) GeolocationServiceBridge::newErrorAvailable }
};

static const char *javaLocationClassName = "android/location/Location";
enum javaLocationClassMethods {
    LocationMethodGetLatitude = 0,
    LocationMethodGetLongitude,
    LocationMethodHasAltitude,
    LocationMethodGetAltitude,
    LocationMethodHasAccuracy,
    LocationMethodGetAccuracy,
    LocationMethodHasBearing,
    LocationMethodGetBearing,
    LocationMethodHasSpeed,
    LocationMethodGetSpeed,
    LocationMethodGetTime,
    LocationMethodCount,
};
static jmethodID javaLocationClassMethodIDs[LocationMethodCount];

GeolocationServiceBridge::GeolocationServiceBridge(Listener* listener, WebViewCore* webViewCore)
    : m_listener(listener)
    , m_javaGeolocationServiceObject(0)
{
    ASSERT(m_listener);
    startJavaImplementation(webViewCore);
}

GeolocationServiceBridge::~GeolocationServiceBridge()
{
    stop();
    stopJavaImplementation();
}

bool GeolocationServiceBridge::start()
{
    if (!m_javaGeolocationServiceObject)
        return false;
    return getJNIEnv()->CallBooleanMethod(m_javaGeolocationServiceObject,
                                          javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStart]);
}

void GeolocationServiceBridge::stop()
{
    if (!m_javaGeolocationServiceObject)
        return;
    getJNIEnv()->CallVoidMethod(m_javaGeolocationServiceObject,
                                javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStop]);
}

void GeolocationServiceBridge::setEnableGps(bool enable)
{
    if (!m_javaGeolocationServiceObject)
        return;
    getJNIEnv()->CallVoidMethod(m_javaGeolocationServiceObject,
                                javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodSetEnableGps],
                                enable);
}

void GeolocationServiceBridge::newLocationAvailable(JNIEnv* env, jclass, jlong nativeObject, jobject location)
{
    ASSERT(nativeObject);
    ASSERT(location);
    GeolocationServiceBridge* object = reinterpret_cast<GeolocationServiceBridge*>(nativeObject);
    object->m_listener->newPositionAvailable(toGeolocationPosition(env, location));
}

void GeolocationServiceBridge::newErrorAvailable(JNIEnv* env, jclass, jlong nativeObject, jstring message)
{
    GeolocationServiceBridge* object = reinterpret_cast<GeolocationServiceBridge*>(nativeObject);
    RefPtr<GeolocationError> error = GeolocationError::create(GeolocationError::PositionUnavailable, jstringToWtfString(env, message));
    object->m_listener->newErrorAvailable(error.release());
}

PassRefPtr<GeolocationPosition> GeolocationServiceBridge::toGeolocationPosition(JNIEnv *env, const jobject &location)
{
    // Altitude is optional and may not be supplied.
    bool hasAltitude =
        env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasAltitude]);
    double Altitude =
        hasAltitude ?
        env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetAltitude]) :
        0.0;
    // Accuracy is required, but is not supplied by the emulator.
    double Accuracy =
        env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasAccuracy]) ?
        env->CallFloatMethod(location, javaLocationClassMethodIDs[LocationMethodGetAccuracy]) :
        0.0;
    // heading is optional and may not be supplied.
    bool hasHeading =
        env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasBearing]);
    double heading =
        hasHeading ?
        env->CallFloatMethod(location, javaLocationClassMethodIDs[LocationMethodGetBearing]) :
        0.0;
    // speed is optional and may not be supplied.
    bool hasSpeed =
        env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasSpeed]);
    double speed =
        hasSpeed ?
        env->CallFloatMethod(location, javaLocationClassMethodIDs[LocationMethodGetSpeed]) :
        0.0;

    return GeolocationPosition::create(
        env->CallLongMethod(location, javaLocationClassMethodIDs[LocationMethodGetTime]) / 1000.0,
        env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetLatitude]),
        env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetLongitude]),
        Accuracy,
        hasAltitude, Altitude,
        false, 0.0,  // AltitudeAccuracy not provided.
        hasHeading, heading,
        hasSpeed, speed);
}

void GeolocationServiceBridge::startJavaImplementation(WebViewCore* webViewCore)
{
    JNIEnv* env = getJNIEnv();

    // Get the Java GeolocationService class.
    jclass javaGeolocationServiceClass = env->FindClass(javaGeolocationServiceClassName);
    ASSERT(javaGeolocationServiceClass);

    // Set up the methods we wish to call on the Java GeolocationService class.
    javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodInit] =
            env->GetMethodID(javaGeolocationServiceClass, "<init>", "(Landroid/content/Context;J)V");
    javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStart] =
            env->GetMethodID(javaGeolocationServiceClass, "start", "()Z");
    javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStop] =
            env->GetMethodID(javaGeolocationServiceClass, "stop", "()V");
    javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodSetEnableGps] =
            env->GetMethodID(javaGeolocationServiceClass, "setEnableGps", "(Z)V");

    // Create the Java GeolocationService object.
    jobject context = webViewCore->getContext();
    if (!context)
        return;
    jlong nativeObject = reinterpret_cast<jlong>(this);
    jobject object = env->NewObject(javaGeolocationServiceClass,
                                    javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodInit],
                                    context,
                                    nativeObject);

    m_javaGeolocationServiceObject = getJNIEnv()->NewGlobalRef(object);
    ASSERT(m_javaGeolocationServiceObject);

    // Register to handle calls to native methods of the Java GeolocationService
    // object. We register once only.
    static int registered = jniRegisterNativeMethods(env,
                                                     javaGeolocationServiceClassName,
                                                     javaGeolocationServiceClassNativeMethods,
                                                     NELEM(javaGeolocationServiceClassNativeMethods));
    ASSERT(registered == JNI_OK);

    // Set up the methods we wish to call on the Java Location class.
    jclass javaLocationClass = env->FindClass(javaLocationClassName);
    ASSERT(javaLocationClass);
    javaLocationClassMethodIDs[LocationMethodGetLatitude] =
        env->GetMethodID(javaLocationClass, "getLatitude", "()D");
    javaLocationClassMethodIDs[LocationMethodGetLongitude] =
        env->GetMethodID(javaLocationClass, "getLongitude", "()D");
    javaLocationClassMethodIDs[LocationMethodHasAltitude] =
        env->GetMethodID(javaLocationClass, "hasAltitude", "()Z");
    javaLocationClassMethodIDs[LocationMethodGetAltitude] =
        env->GetMethodID(javaLocationClass, "getAltitude", "()D");
    javaLocationClassMethodIDs[LocationMethodHasAccuracy] =
        env->GetMethodID(javaLocationClass, "hasAccuracy", "()Z");
    javaLocationClassMethodIDs[LocationMethodGetAccuracy] =
        env->GetMethodID(javaLocationClass, "getAccuracy", "()F");
    javaLocationClassMethodIDs[LocationMethodHasBearing] =
        env->GetMethodID(javaLocationClass, "hasBearing", "()Z");
    javaLocationClassMethodIDs[LocationMethodGetBearing] =
        env->GetMethodID(javaLocationClass, "getBearing", "()F");
    javaLocationClassMethodIDs[LocationMethodHasSpeed] =
        env->GetMethodID(javaLocationClass, "hasSpeed", "()Z");
    javaLocationClassMethodIDs[LocationMethodGetSpeed] =
        env->GetMethodID(javaLocationClass, "getSpeed", "()F");
    javaLocationClassMethodIDs[LocationMethodGetTime] =
        env->GetMethodID(javaLocationClass, "getTime", "()J");
}

void GeolocationServiceBridge::stopJavaImplementation()
{
    if (!m_javaGeolocationServiceObject)
        return;
    getJNIEnv()->DeleteGlobalRef(m_javaGeolocationServiceObject);
}

} // namespace android
